Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: github.com/ImageMagick/ImageMagick
Language: C
File: coders/wpg.c
Function: ExtractPostscript

Call path: ReadWPGImage (coders/wpg.c) → ExtractPostscript (coders/wpg.c) → GetMagicInfo (MagickCore/magic.c) → ReadImage (MagickCore/image.c)

### Primary Function

```c
static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
  MagickOffsetType PS_Offset,ssize_t PS_Size,ExceptionInfo *exception)
{
  char
    postscript_file[MaxTextExtent];

  const MagicInfo
    *magic_info;

  FILE
    *ps_file;

  ImageInfo
    *clone_info;

  Image
    *image2;

  unsigned char
    magick[2*MaxTextExtent];

  if ((clone_info=CloneImageInfo(image_info)) == NULL)
    return(image);
  clone_info->blob=(void *) NULL;
  clone_info->length=0;

  /* Obtain temporary file */
  (void) AcquireUniqueFilename(postscript_file);
  ps_file=fopen_utf8(postscript_file,"wb");
  if (ps_file == (FILE *) NULL)
    goto FINISH;

  /* Copy postscript to temporary file */
  (void) SeekBlob(image,PS_Offset,SEEK_SET);
  (void) ReadBlob(image, 2*MaxTextExtent, magick);

  (void) SeekBlob(image,PS_Offset,SEEK_SET);
  while(PS_Size-- > 0)
    {
      (void) fputc(ReadBlobByte(image),ps_file);
    }
  (void) fclose(ps_file);

    /* Detect file format - Check magic.mgk configuration file. */
  magic_info=GetMagicInfo(magick,2*MaxTextExtent,exception);
  if(magic_info == (const MagicInfo *) NULL) goto FINISH_UNL;
  /*     printf("Detected:%s  \n",magic_info->name); */
  if(exception->severity != UndefinedException) goto FINISH_UNL;
  if(magic_info->name == (char *) NULL) goto FINISH_UNL;

  (void) strncpy(clone_info->magick,magic_info->name,MaxTextExtent);

    /* Read nested image */
  /*FormatString(clone_info->filename,"%s:%s",magic_info->name,postscript_file);*/
  FormatLocaleString(clone_info->filename,MaxTextExtent,"%s",postscript_file);
  image2=ReadImage(clone_info,exception);

  if (!image2)
    goto FINISH_UNL;

  /*
    Replace current image with new image while copying base image
    attributes.
  */
  (void) CopyMagickString(image2->filename,image->filename,MaxTextExtent);
  (void) CopyMagickString(image2->magick_filename,image->magick_filename,MaxTextExtent);
  (void) CopyMagickString(image2->magick,image->magick,MaxTextExtent);
  image2->depth=image->depth;
  DestroyBlob(image2);
  image2->blob=ReferenceBlob(image->blob);

  if ((image->rows == 0) || (image->columns == 0))
    DeleteImageFromList(&image);

  AppendImageToList(&image,image2);

 FINISH_UNL:
  (void) RelinquishUniqueFileResource(postscript_file);
 FINISH:
  DestroyImageInfo(clone_info);
  return(image);
}
```

### Cross-File Context

[MaxTextExtent — macro — MagickCore/method-attribute.h:80]
MaxTextExtent → MagickPathExtent  (MagickCore/method-attribute.h:80)

[MagickPathExtent — macro — MagickCore/method-attribute.h:79]
MagickPathExtent → 4096  (MagickCore/method-attribute.h:79)

[_MagicInfo — struct — MagickCore/magic.c:82]
```c
struct _MagicInfo
{
  char
    *name;

  unsigned char
    *magic;

  size_t
    length;

  MagickOffsetType
    offset;

  MagickBooleanType
    skip_spaces;

  size_t
    signature;
};
```

[_ImageInfo — struct — MagickCore/image.h:358]
```c
struct _ImageInfo
{
  ...
  char
    magick[MagickPathExtent],    /* image file format (file magick) */
  ...
};
```

[GetMagicInfo — callee — MagickCore/magic.c:303]
```c
MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
  const size_t length,ExceptionInfo *exception)
```

Control flow: ReadWPGImage parses a WPG file and calls ExtractPostscript when encountering embedded PostScript data (record type 0x11). ExtractPostscript creates a temporary file, writes PostScript data to it, uses GetMagicInfo to detect the file format based on magic bytes, then uses strncpy to copy the detected format name into clone_info->magick before calling ReadImage to read the nested image.

Data flow: The magick format name flows from GetMagicInfo (which returns a MagicInfo struct with a name field) through strncpy into clone_info->magick buffer, then to ReadImage which uses clone_info->magick to determine the image format. The vulnerability occurs when the name field is >= 4096 bytes, causing strncpy to not null-terminate the 4096-byte magick buffer.

Verdict: Vulnerable
Vulnerable region:
[coders/wpg.c]
```c
/*     printf("Detected:%s  \n",magic_info->name); */
```
CWE: CWE-189
Severity: MEDIUM

Root cause: The strncpy at line 806 in coders/wpg.c copies at most MaxTextExtent (4096) bytes from magic_info->name into clone_info->magick, which is declared as char magick[MagickPathExtent] (also 4096 bytes). When magic_info->name is exactly MaxTextExtent (4096) bytes or longer, strncpy fills the entire buffer without null-terminating it, because strncpy only guarantees null-termination when the source string is strictly shorter than the specified size.

Exploitability: An attacker can craft a WPG file containing embedded PostScript data with a magic name that is 4096 bytes or longer, triggering the missing null-termination vulnerability when ImageMagick processes the file.

Attack preconditions:
- Attacker can provide a specially crafted WPG file to ImageMagick for processing
- The WPG file must contain embedded PostScript data with a detected magic format name >= 4096 characters

Likely impact: An attacker can craft a WPG file containing embedded PostScript data with a magic name that is 4096 bytes or longer, triggering the missing null-termination vulnerability when ImageMagick processes the file.

ReadWPGImage ExtractPostscript GetMagicInfo ReadImage

The provided code snippet for the `ExtractPostscript` function in `coders/wpg.c` contains a potential **out-of-bounds read** vulnerability.

### Analysis

1.  **Buffer Allocation**:
    The buffer `magick` is defined as:
    ```c
    unsigned char magick[2*MaxTextExtent]; // 2 * 4096 = 8192 bytes
    ```

2.  **Unbounded/Unchecked Read**:
    The function attempts to read into this buffer from the image blob:
    ```c
    (void) SeekBlob(image, PS_Offset, SEEK_SET);
    (void) ReadBlob(image, 2*MaxTextExtent, magick);
    ```
    The variable `PS_Size` (the size of the embedded Postscript data) is passed to the function. However, the code performs a fixed-size read of `2*MaxTextExtent` into `magick` regardless of the actual value of `PS_Size`. If `PS_Size` is smaller than `2*MaxTextExtent` (8192 bytes), the code might attempt to read past the intended boundary of the embedded object in the WPG file. While `ReadBlob` usually handles EOF safely, there is a mismatch between the object size and the magic detection buffer size.

3.  **The "Postscript" Loop**:
    ```c
    while(PS_Size-- > 0)
    {
      (void) fputc(ReadBlobByte(image), ps_file);
    }
    ```
    If `PS_Size` is controlled by the input file (which it is, in WPG parsing), an attacker can provide a very large value for `PS_Size`. This loop will continue until `PS_Size` reaches 0. If the underlying blob is shorter than `PS_Size`, `ReadBlobByte` will return `EOF`, and `fputc` will write `0xFF` (the casted EOF) repeatedly into the temporary file until the disk fills or the process is terminated. This presents a **Denial of Service (DoS)** risk via resource exhaustion (disk space/CPU).

4.  **Information Leak / Logic Error**:
    The call `magic_info=GetMagicInfo(magick, 2*MaxTextExtent, exception);` passes the full 8192 bytes to the magic detection engine. If the actual embedded data was only, for example, 10 bytes, `GetMagicInfo` is analyzing 10 bytes of actual data followed by 8182 bytes of whatever was next in the WPG file (or uninitialized memory if the read failed). This can lead to misidentification of the nested file format or an information leak if the results of this detection influence subsequent logic or error messages.

### Summary
The primary vulnerability is a **Denial of Service (Resource Exhaustion)** due to the unchecked `PS_Size` loop. Additionally, there is a risk of **out-of-bounds reads** or logic errors because the code assumes the embedded object is at least `2*MaxTextExtent` bytes long when filling the magic detection buffer.

### Recommendation
The code should validate that `PS_Size` is within reasonable bounds and matches the available data in the blob. The read into the `magick` buffer should be limited by `PS_Size`:
```c
size_t read_size = (size_t)PS_Size < 2*MaxTextExtent ? (size_t)PS_Size : 2*MaxTextExtent;
(void) ReadBlob(image, read_size, magick);
magic_info = GetMagicInfo(magick, read_size, exception);
```

static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
  MagickOffsetType PS_Offset,ssize_t PS_Size,ExceptionInfo *exception)
{
  ...
  /* Copy postscript to temporary file */
  (void) SeekBlob(image,PS_Offset,SEEK_SET);
  (void) ReadBlob(image, 2*MaxTextExtent, magick);

  (void) SeekBlob(image,PS_Offset,SEEK_SET);
  while(PS_Size-- > 0)
    {
      (void) fputc(ReadBlobByte(image),ps_file);
    }
  (void) fclose(ps_file);
  ...

The function performs an unchecked read and write loop based on the PS_Size parameter provided by the input file. First, it attempts to read a fixed buffer size (2*MaxTextExtent) into the 'magick' array without verifying if PS_Size is at least that large, potentially leading to out-of-bounds reads or processing of data outside the intended object. Second, the while loop writing to a temporary file is controlled by PS_Size without checking for EOF or limiting the size, which can lead to disk exhaustion if a malicious file provides a massive PS_Size value.

High. An attacker can craft a WPG file with a large PS_Size value and a small amount of actual data. The ReadBlobByte function will return EOF (typically -1), which is cast to unsigned char and written to disk repeatedly.

The attacker must be able to provide a crafted WPG image file to be processed by ImageMagick.

Denial of Service (DoS) via disk space exhaustion and CPU consumption. Potential information leak if magic detection processes data beyond the embedded object's boundaries.

The amount of data read and written from an embedded object should never exceed the declared size of that object (PS_Size) or the remaining bytes in the source blob.

The code violates this by reading a hardcoded 2*MaxTextExtent bytes into 'magick' regardless of PS_Size, and by failing to check for EOF or stream errors within the while loop that copies data to the temporary file.

While ImageMagick has added many security policies to limit resource usage (like disk space), the underlying logic here is still inherently flawed by trusting the size field from the file format without validation.

ReadWPGImage (coders/wpg.c) -> ExtractPostscript (coders/wpg.c)


System:
You are a senior application security auditor reviewing code for potential vulnerabilities.

You will be given a candidate function, repository and file metadata, a reduced call path, and resolved cross-file context such as helper functions, structs, macros, constants, and related definitions. Use the supplied context actively, but stay strictly grounded in what is actually shown.

Work from the supplied code and surrounding context as the primary evidence. Do not assume a bug exists just because the sample was retrieved.

Analyze both control flow and data flow. Trace the relevant execution paths and track security-relevant data through inputs, transformations, conditions, helper calls, outputs, and side effects.

Reason about attacker influence, identify relevant guards or missing guards, and explain exploitability or non-exploitability before reaching a verdict.

When the code is vulnerable, explain the vulnerable behavior, root cause, realistic attack preconditions, likely impact, and the most precise vulnerability classification justified by the supplied code.

When the code is not vulnerable, explain the concrete invariants and guards that prevent the suspected issue, and note any residual uncertainty that remains from the supplied context.

Keep the analysis concrete and code-grounded. Separate observed evidence from inferred conclusion.

Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Language: C
File: include/net/netns/hash.h
Function: net_hash_mix

Call path: net_hash_mix (include/net/netns/hash.h) → udp_hashfn (include/linux/udp.h) → inet_ehashfn (include/net/inet_hashtables.h) → inet6_ehashfn (include/net/inet6_hashtables.h) → inet_bhashfn (include/net/inet_hashtables.h) → inet_lhashfn (include/net/inet_hashtables.h) → ping_hashfn (net/ipv4/ping.c)

### Primary Function

```c
static inline u32 net_hash_mix(const struct net *net)
{
#ifdef CONFIG_NET_NS
	return (u32)(((unsigned long)net) >> ilog2(sizeof(*net)));
#else
	return 0;
#endif
}
```

### Cross-File Context

[hash_mix — field — include/net/net_namespace.h (struct net)]
u32 hash_mix;

Provide the final verdict as strict JSON.

Return only one JSON object and no surrounding prose.

Return one JSON object with these keys:
- vulnerable
- cwe
- severity
- reviewed_region
- vulnerable_region
- root_cause
- exploitability
- attack_preconditions
- impact
- non_vulnerable_reason
- security_invariants
- invariant_verification
- residual_risk_notes
- call_path

Control flow: net_hash_mix() is a static inline function used by hash functions for socket lookup tables. It takes a struct net pointer and returns a u32. Pre-fix: returns pointer address bits via bit shift. Post-fix: returns struct net->hash_mix random field.

Data flow: Pre-fix: struct net pointer address -> cast to u32 -> right shift by ilog2(sizeof(struct net)) -> return. The pointer value comes from kernel text/static data for init_net. Post-fix: struct net->hash_mix (random u32) -> return. The hash_mix is initialized via get_random_bytes() during setup_net().

Verdict: Vulnerable
Vulnerable region:
[include/net/netns/hash.h]
```c
struct net;

static inline u32 net_hash_mix(const struct net *net)
{
#ifdef CONFIG_NET_NS
	return (u32)(((unsigned long)net) >> ilog2(sizeof(*net)));
```
CWE: CWE-326
Severity: MEDIUM

Root cause: The net_hash_mix() function used the kernel address of struct net as its return value. When CONFIG_NET_NS=y and the network namespace was the initial init_net (statically allocated, not dynamically allocated), the pointer value remained constant across boots and revealed kernel text address boundaries. This allowed remote attackers to infer kernel image offsets via IP ID hash collisions, defeating KASLR protection.

Exploitability: Remote attacker forces target to send UDP/ICMP to attacker-controlled IPs, observes IP ID values, detects hash collisions in net_hash_mix outputs, enumerates to extract kernel text address bits. Requires only ability to cause network traffic from target, trivial for DNS servers or pingable hosts.

Attack preconditions:
- Target must send UDP/ICMP/traffic to attacker-controlled IP addresses
- Attacker must observe IP ID values in returned packets
- Target kernel must have CONFIG_NET_NS enabled (default on server distributions)
- For init_net exploit: struct net must be statically allocated (not dynamically) so address is predictable across boots

Likely impact: Remote attacker forces target to send UDP/ICMP to attacker-controlled IPs, observes IP ID values, detects hash collisions in net_hash_mix outputs, enumerates to extract kernel text address bits. Requires only ability to cause network traffic from target, trivial for DNS servers or pingable hosts.

Analysis of the provided code reveals a **real vulnerability** related to information disclosure (KASLR bypass) and potential algorithmic Denial of Service (DoS).

### Analysis

The function `net_hash_mix` is designed to provide a unique value for each network namespace (`struct net`) to salt hash calculations for various networking protocols (UDP, TCP, Ping, etc.).

```c
static inline u32 net_hash_mix(const struct net *net)
{
#ifdef CONFIG_NET_NS
	return (u32)(((unsigned long)net) >> ilog2(sizeof(*net)));
#else
	return 0;
#endif
}
```

#### 1. Information Disclosure (KASLR Bypass)
The implementation derives the hash salt directly from the **kernel memory address** of the `struct net` object.
- **Mechanism**: By shifting the pointer `net` and casting it to a `u32`, the function leaks bits of a kernel heap address into network hashes.
- **Impact**: Many networking stack properties (like TCP sequence numbers, source ports, or fragment IDs) are influenced by these hashes. If an attacker can observe these values or infer hash bucket positions (e.g., through timing attacks or sequence number analysis), they can reverse-calculate the `net_hash_mix` value. Since the value is derived linearly from a kernel pointer, this effectively breaks Kernel Address Space Layout Randomization (KASLR) for the heap.

#### 2. Hash Collision / Algorithmic DoS
- **Mechanism**: The logic `>> ilog2(sizeof(*net))` simply removes the alignment bits. Because `struct net` objects are typically allocated from a specific slab cache, their addresses are highly predictable and often follow a linear sequence.
- **Impact**: In a multi-tenant environment (like a containerized cloud), an attacker in one namespace can predict the `net_hash_mix` of other namespaces. This allows for the crafting of packets that cause heavy hash collisions across the system's global protocol tables (like the established TCP connection table), leading to significant CPU exhaustion and performance degradation.

### Verification of Context
The "Cross-File Context" snippet shows that `struct net` already contains a field `u32 hash_mix;`. This field is intended to store a cryptographically secure random value generated when the namespace is created. The provided implementation of `net_hash_mix` **ignores this random field** and uses the pointer instead, which is the root of the vulnerability.

### Conclusion
This pattern was a known issue in the Linux kernel and has been patched in modern versions. The fix involves changing the function to return the randomly initialized `net->hash_mix` instead of calculating a value based on the object's memory address.

**Status: Vulnerable**
**Vulnerability Type:** Information Exposure / KASLR Bypass / Algorithmic Denial of Service

The function derives a hash salt directly from a kernel memory address (pointer to struct net) rather than a cryptographically secure random value. This leaks kernel memory layout information and provides predictable inputs for hash functions used in networking protocols.

Medium. While an attacker cannot directly read the return value, they can infer it by observing network side-channels such as TCP sequence numbers, ephemeral port selection, or hash bucket collisions in protocols like UDP or Ping.

Requires the ability to observe or interact with network traffic generated within a network namespace, or a multi-tenant environment where an attacker shares a host with other namespaces.

Breaks KASLR (Kernel Address Space Layout Randomization) by leaking bits of kernel heap addresses. Additionally, it enables algorithmic Denial of Service (DoS) attacks by allowing an attacker to predict hash seeds and trigger collisions in global network tables.

Hash seeds used to distribute traffic or randomize protocol identifiers must be unpredictable to prevent cross-namespace interference and information leakage.

The implementation fails the invariant by using a linear transformation of a static kernel pointer as a 'mix' value, which is both predictable and sensitive.

The fix involves using the pre-initialized random 'hash_mix' field within the 'struct net' instead of the object's address.


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Language: C
File: net/ipv4/tcp_input.c
Function: tcp_cwnd_reduction

Call path: tcp_enter_cwr (net/ipv4/tcp_input.c) → tcp_init_cwnd_reduction (net/ipv4/tcp_input.c) → tcp_cwnd_reduction (net/ipv4/tcp_input.c) → tcp_try_keep_open (net/ipv4/tcp_input.c) → tcp_process_loss (net/ipv4/tcp_input.c) → tcp_fastretrans_alert (net/ipv4/tcp_input.c)

### Primary Function

```c
static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
				       int fast_rexmit, int flag)
{
	struct tcp_sock *tp = tcp_sk(sk);
	int sndcnt = 0;
	int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
	int newly_acked_sacked = prior_unsacked -
				 (tp->packets_out - tp->sacked_out);

	if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
		return;

	tp->prr_delivered += newly_acked_sacked;
	if (delta < 0) {
		u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
			       tp->prior_cwnd - 1;
		sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
	} else if ((flag & FLAG_RETRANS_DATA_ACKED) &&
		   !(flag & FLAG_LOST_RETRANS)) {
		sndcnt = min_t(int, delta,
			       max_t(int, tp->prr_delivered - tp->prr_out,
				     newly_acked_sacked) + 1);
	} else {
		sndcnt = min(delta, newly_acked_sacked);
	}
	sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
	tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}
```

### Cross-File Context

[tcp_init_cwnd_reduction — helper — net/ipv4/tcp_input.c:2458-2470]
```c
static void tcp_init_cwnd_reduction(struct sock *sk)
{
	struct tcp_sock *tp = tcp_sk(sk);

	tp->high_seq = tp->snd_nxt;
	tp->tlp_high_seq = 0;
	tp->snd_cwnd_cnt = 0;
	tp->prior_cwnd = tp->snd_cwnd;
	tp->prr_delivered = 0;
	tp->prr_out = 0;
	tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk);
	tcp_ecn_queue_cwr(tp);
}
```

[tcp_packets_in_flight — function — include/net/tcp.h:997-1001]
```c
static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
{
	return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
}
```

[div_u64 — function — include/linux/math64.h:96-100]
```c
static inline u64 div_u64(u64 dividend, u32 divisor)
{
	u32 remainder;
	return div_u64_rem(dividend, divisor, &remainder);
}
```

[WARN_ON_ONCE — macro — include/asm-generic/bug.h:109-118]
WARN_ON_ONCE → #define WARN_ON_ONCE(condition) ({ \ static bool __section(.data.unlikely) __warned; \ int __ret_warn_once = !!(condition); \ \ if (unlikely(__ret_warn_once)) \ if (WARN_ON(!__warned)) \ __warned = true; \ unlikely(__ret_warn_once); \ })  (include/asm-generic/bug.h:109-118)

[struct tcp_sock — struct — include/linux/tcp.h:132-350]
```c
struct tcp_sock {
	/* inet_connection_sock has to be the first member of tcp_sock */
	struct inet_connection_sock	inet_conn;
	u16	tcp_header_len;
	u16	gso_segs;
	__be32	pred_flags;
	u64	bytes_received;
	u32	segs_in;
	u32	rcv_nxt;
	u32	copied_seq;
	u32	rcv_wup;
	u32	snd_nxt;
	u32	segs_out;
	u64	bytes_acked;
	struct u64_stats_sync syncp;
	u32	snd_una;
	u32	snd_sml;
	u32	rcv_tstamp;
	u32	lsndtime;
	u32	last_oow_ack_time;
	u32	tsoffset;
	struct list_head tsq_node;
	unsigned long	tsq_flags;
	struct {
		struct sk_buff_head	prequeue;
		struct task_struct	*task;
		struct msghdr		*msg;
		int			memory;
		int			len;
	} ucopy;
	u32	snd_wl1;
	u32	snd_wnd;
	u32	max_window;
	u32	mss_cache;
	u32	window_clamp;
	u32	rcv_ssthresh;
	struct tcp_rack rack;
	u16	advmss;
	u8	unused;
	u8	nonagle     : 4;
	u8	thin_lto    : 1;
	u8	thin_dupack : 1;
	u8	repair      : 1;
	u8	frto        : 1;
	u8	repair_queue;
	u8	do_early_retrans:1;
	u8	syn_data:1;
	u8	syn_fastopen:1;
	u8	syn_fastopen_exp:1;
	u8	syn_data_acked:1;
	u8	save_syn:1;
	u8	is_cwnd_limited:1;
	u32	tlp_high_seq;
	u32	srtt_us;
	u32	mdev_us;
	u32	mdev_max_us;
	u32	mdev_max_us;
	u32	rttvar_us;
	u32	rtt_seq;
	struct rtt_meas rtt_min[3];
	u32	packets_out;
	u32	retrans_out;
	u32	max_packets_out;
	u32	max_packets_seq;
	u16	urg_data;
	u8	ec n_flags;
	u8	keepalive_probes;
	u32	reordering;
	u32	snd_up;
	struct tcp_options_received rx_opt;
	u32	snd_ssthresh;
	u32	snd_cwnd;
	u32	snd_cwnd_cnt;
	u32	snd_cwnd_clamp;
	u32	snd_cwnd_used;
	u32	snd_cwnd_stamp;
	u32	prior_cwnd;
	u32	prr_delivered;
	u32	prr_out;
	u32	rcv_wnd;
	u32	write_seq;
	u32	notsent_lowat;
	u32	pushed_seq;
	u32	lost_out;
	u32	sacked_out;
	u32	fackets_out;
	struct sk_buff* lost_skb_hint;
	struct sk_buff *retransmit_skb_hint;
	struct sk_buff_head out_of_order_queue;
	struct tcp_sack_block duplicate_sack[1];
	struct tcp_sack_block selective_acks[4];
	struct tcp_sack_block recv_sack_cache[4];
	struct sk_buff *highest_sack;
	int     lost_cnt_hint;
	u32     retransmit_high;
	u32	prior_ssthresh;
	u32	high_seq;
	u32	retrans_stamp;
	u32	undo_marker;
	int	undo_retrans;
	u32	total_retrans;
	/* ... more fields ... */
}
```

[FLAG_RETRANS_DATA_ACKED — constant — net/ipv4/tcp_input.c:109]
FLAG_RETRANS_DATA_ACKED → 0x08 /* Some of which was retransmitted */  (net/ipv4/tcp_input.c:109)

[FLAG_LOST_RETRANS — constant — net/ipv4/tcp_input.c:114]
FLAG_LOST_RETRANS → 0x80 /* This ACK marks some retransmission lost */  (net/ipv4/tcp_input.c:114)

Control flow: The function tcp_cwnd_reduction begins by computing intermediate values (delta, newly_acked_sacked). An early return guard checks whether newly_acked_sacked is positive AND tp->prior_cwnd is non-zero; if either condition fails, the function returns immediately without executing any subsequent logic. When execution continues past the guard, one of three branches computes sndcnt based on delta's sign and flag values. In the delta < 0 branch, div_u64 is called with tp->prior_cwnd as divisor. All three branches flow to updating tp->snd_cwnd as the final operation.

Data flow: Inputs prior_unsacked, fast_rexmit, and flag are combined with tp fields to compute newly_acked_sacked and delta. tp->prior_cwnd originates from tcp_init_cwnd_reduction which sets it to tp->snd_cwnd. The newly_acked_sacked value is added to tp->prr_delivered. When delta < 0, a dividend is computed using tp->snd_ssthresh, tp->prr_delivered, and tp->prior_cwnd, then divided by tp->prior_cwnd via div_u64. The resulting sndcnt (constrained by fast_rexmit and delta logic) is added to tcp_packets_in_flight(tp) to set tp->snd_cwnd.

Verdict: Not Vulnerable

Reviewed region:
[net/ipv4/tcp_input.c]
```c
static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
				       int fast_rexmit, int flag)
{
	struct tcp_sock *tp = tcp_sk(sk);
	int sndcnt = 0;
	int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);
	int newly_acked_sacked = prior_unsacked -
				 (tp->packets_out - tp->sacked_out);

	if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
		return;

	tp->prr_delivered += newly_acked_sacked;
	if (delta < 0) {
		u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
			       tp->prior_cwnd - 1;
		sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
	} else if ((flag & FLAG_RETRANS_DATA_ACKED) &&
		   !(flag & FLAG_LOST_RETRANS)) {
		sndcnt = min_t(int, delta,
			       max_t(int, tp->prr_delivered - tp->prr_out,
				     newly_acked_sacked) + 1);
	} else {
		sndcnt = min(delta, newly_acked_sacked);
	}
	sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
	tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}
```

Why it is not vulnerable: The division by tp->prior_cwnd in the delta < 0 branch (div_u64(dividend, tp->prior_cwnd)) is protected by an early return guard at the function entry: 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;'. The short-circuit evaluation of the || operator ensures that if tp->prior_cwnd is zero, the function returns before reaching the division operation. This guard is evaluated before any code path that uses tp->prior_cwnd as a divisor.

Security invariants:
- tp->prior_cwnd must be non-zero before div_u64(dividend, tp->prior_cwnd) is reached. This is enforced by the guard 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;' which uses short-circuit || evaluation, guaranteeing early return when tp->prior_cwnd is zero.
- The short-circuit evaluation of || ensures the WARN_ON_ONCE(!tp->prior_cwnd) check is always evaluated before any division by tp->prior_cwnd occurs, since the return statement immediately follows the guard.
- tcp_init_cwnd_reduction sets tp->prior_cwnd = tp->snd_cwnd, establishing that prior_cwnd reflects the congestion window value at the time congestion control state is initialized.

Invariant verification:
- Division by zero prevention for tp->prior_cwnd: holds=true. Evidence: The guard 'if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return;' at the function entry ensures tp->prior_cwnd != 0 before any subsequent code executes, including the div_u64(dividend, tp->prior_cwnd) call in the delta < 0 branch. The || operator's short-circuit semantics guarantee the check is evaluated and the return is taken if prior_cwnd is zero.
- All code paths reaching division pass the non-zero guard: holds=true. Evidence: The function has a single entry point and the guard is placed before all computational branches. The delta < 0 branch containing div_u64(dividend, tp->prior_cwnd) can only be reached after the guard has confirmed tp->prior_cwnd is non-zero.

Residual risk notes: The safety of the division relies on tp->prior_cwnd remaining non-zero between the guard check and the div_u64 call. If concurrent modification of tp->prior_cwnd were possible, a TOCTOU issue could arise. However, the surrounding TCP input processing context typically holds the socket lock (sk_lock), serializing access to these fields. Without visibility into the locking discipline in the callers, this assumption cannot be fully verified from the supplied context alone.

No concrete vulnerability impact is demonstrated in the supplied code and context.

Analysis of the provided code for `tcp_cwnd_reduction` reveals a potential **integer overflow** vulnerability in the calculation of `sndcnt` when `delta < 0`.

### Vulnerability Analysis

The vulnerability resides in the PRR (Proportional Rate Reduction) calculation:

```c
if (delta < 0) {
    u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
                   tp->prior_cwnd - 1;
    sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
}
```

1.  **Type Mismatch/Overflow**: `sndcnt` is declared as a signed `int`. The result of `div_u64(dividend, tp->prior_cwnd)` is a `u64`. While `tp->snd_ssthresh` and `tp->prr_delivered` are `u32`, their product (stored in a `u64`) can be very large. If the resulting `u64` value from `div_u64` is greater than `INT_MAX` (2,147,483,647), assigning it to `sndcnt` results in an implementation-defined value (typically wrapping to a negative number).
2.  **Logic Flaw in `sndcnt`**: If `tp->prr_out` is larger than the quotient, `sndcnt` becomes negative. Later, `sndcnt` is used here:
    ```c
    sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
    tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
    ```
    While the `max` call prevents `sndcnt` from being negative if it was small, it does not protect against a massive positive overflow of a signed integer that wrapped to a negative value.
3.  **Impact on `snd_cwnd`**: The congestion window (`tp->snd_cwnd`) is a critical control parameter. An incorrect `sndcnt` calculation can cause `snd_cwnd` to be set to an inappropriately small or large value. In specific scenarios where a connection remains in recovery for a very long time (high `prr_delivered`), the `u64` result could theoretically exceed the capacity of a signed `int`.

### Supporting Context
In the Linux Kernel, this specific logic was identified as problematic because PRR should ideally not allow `sndcnt` to result in a `snd_cwnd` that allows more packets than the network can handle. If `sndcnt` becomes a large negative number due to signed integer overflow, `snd_cwnd` might drop to near-zero or wrap around depending on how `tcp_packets_in_flight` interacts with it.

Historically, this function had an issue where `snd_cwnd` could be set to a value that allowed a massive burst of packets if `sndcnt` was miscalculated, or conversely, it could stall the connection.

### Conclusion
While a direct "exploit" is difficult to trigger without specific network conditions (requires very large values of `prr_delivered` or specific `ssthresh` values), the code lacks sufficient bounds checking for the transition from `u64` arithmetic to a signed `int` `sndcnt`.

**Verdict:** Real Vulnerability (Integer Overflow/Sign Conversion Issue)

The calculation of 'sndcnt' uses u64 arithmetic but stores the result in a signed integer ('int'). In scenarios with very large congestion windows or long-duration recovery (leading to high prr_delivered), the result of the division can exceed INT_MAX, causing a signed integer overflow/wrap-around. This leads to an incorrect congestion window calculation.

Requires a network path and TCP state where the Proportional Rate Reduction (PRR) logic is active for a sustained period with very large values for snd_ssthresh and prr_delivered.

Incorrect congestion window (snd_cwnd) adjustment, potentially leading to connection stalls or unintended packet bursts, disrupting network stability for the affected flow.

The congestion control algorithm must ensure that the number of packets sent (sndcnt) does not overflow the underlying data types used to update the congestion window.

The code fails this invariant because it does not check if the u64 result of the PRR formula fits within the signed int 'sndcnt' before subtraction and assignment.

Modern kernels have updated this logic to use more robust bounds checking and different typing to prevent overflow in PRR calculations.

tcp_fastretrans_alert -> tcp_process_loss -> tcp_try_keep_open -> tcp_cwnd_reduction


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Language: C
File: net/ceph/auth_x.c
Function: ceph_x_decrypt

Call path: ceph_x_handle_reply (net/ceph/auth_x.c) → ceph_x_proc_ticket_reply (net/ceph/auth_x.c) → process_one_ticket (net/ceph/auth_x.c) → ceph_x_decrypt (net/ceph/auth_x.c) → ceph_decode_copy (include/linux/ceph/decode.h)

### Primary Function

```c
static int ceph_x_decrypt(struct ceph_crypto_key *secret,
			  void **p, void *end, void *obuf, size_t olen)
{
	struct ceph_x_encrypt_header head;
	size_t head_len = sizeof(head);
	int len, ret;

	len = ceph_decode_32(p);
	if (*p + len > end)
		return -EINVAL;

	dout("ceph_x_decrypt len %d\n", len);
	ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
			    *p, len);
	if (ret)
		return ret;
	if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
		return -EPERM;
	*p += len;
	return olen;
}
```

### Cross-File Context

[TEMP_TICKET_BUF_LEN — macro — net/ceph/auth_x.c:16]
TEMP_TICKET_BUF_LEN → 256  (net/ceph/auth_x.c:16)

[CEPHX_ENC_MAGIC — constant — net/ceph/auth_x_protocol.h:83]
CEPHX_ENC_MAGIC → 0xff009cad8826aa55ull  (net/ceph/auth_x_protocol.h:83)

[ceph_x_encrypt_header — struct — net/ceph/auth_x_protocol.h:85-88]
```c
struct ceph_x_encrypt_header {\n\t__u8 struct_v;\n\t__le64 magic;\n} __attribute__ ((packed));
```

[ceph_decode_copy — sink — include/linux/ceph/decode.h:41-45]
ceph_decode_copy → static inline void ceph_decode_copy(void **p, void *pv, size_t n)\n{\n\tmemcpy(pv, *p, n);\n\t*p += n;\n}  (include/linux/ceph/decode.h:41-45)

[ceph_decode_32 — function — include/linux/ceph/decode.h:23-28]
```c
static inline u32 ceph_decode_32(void **p)\n{\n\tu32 v = get_unaligned_le32(*p);\n\t*p += sizeof(u32);\n\treturn v;\n}
```

[ceph_decode_8_safe — macro — include/linux/ceph/decode.h:76-80]
ceph_decode_8_safe → #define ceph_decode_8_safe(p, end, v, bad)\t \t\n\tdo {\t\t\t\t\t\t\t\t\t\n\t\tceph_decode_need(p, end, sizeof(u8), bad);\t\n\t\tv = ceph_decode_8(p);\t\t\t\t\n\t} while (0)  (include/linux/ceph/decode.h:76-80)

[ceph_decode_32_safe — macro — include/linux/ceph/decode.h:66-70]
ceph_decode_32_safe → #define ceph_decode_32_safe(p, end, v, bad)\t \t\n\tdo {\t\t\t\t\t\t\t\t\t\n\t\tceph_decode_need(p, end, sizeof(u32), bad);\t\n\t\tv = ceph_decode_32(p);\t\t\t\t\n\t} while (0)  (include/linux/ceph/decode.h:66-70)

[ceph_decode_need — macro — include/linux/ceph/decode.h:55-59]
ceph_decode_need → #define ceph_decode_need(p, end, n, bad)\t\t\t\n\tdo {\t\t\t\t\t\t\t\t\n\t\tif (!likely(ceph_has_room(p, end, n)))\t\t\n\t\t\tgoto bad;\t\t\t\t\t\n\t} while (0)  (include/linux/ceph/decode.h:55-59)

Control flow: ceph_x_handle_reply dispatches to ceph_x_proc_ticket_reply which iterates over ticket replies calling process_one_ticket for each. process_one_ticket calls ceph_x_decrypt to decrypt ticket data. The pre-fix code passes a fixed 256-byte buffer to ceph_x_decrypt which is insufficient for large tickets. ceph_decrypt2 internally calls ceph_decode_copy which performs the unbounded memcpy causing overflow.

Data flow: The ticket data originates from the Ceph Monitor in the network protocol. It is decoded from wire format via ceph_decode_32() to determine length 'dlen'. In the pre-fix code, this dlen value controls a memcpy into a 256-byte fixed buffer without validation against TEMP_TICKET_BUF_LEN. The attacker controls the ticket length in the protocol, enabling arbitrary overflow up to available memory.

Verdict: Vulnerable
Vulnerable region:
[net/ceph/auth_x.c]
```c
static int ceph_x_decrypt(struct ceph_crypto_key *secret,
			  void **p, void *end, void *obuf, size_t olen)
{
	struct ceph_x_encrypt_header head;
	size_t head_len = sizeof(head);
	int len, ret;

	len = ceph_decode_32(p);
	if (*p + len > end)
		return -EINVAL;

	dout("ceph_x_decrypt len %d\n", len);
	ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
			    *p, len);
	if (ret)
		return ret;
	if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
		return -EPERM;
	*p += len;
	return olen;
}
```
CWE: CWE-399
Severity: HIGH

Root cause: The TEMP_TICKET_BUF_LEN macro hardcodes a 256-byte buffer for cephx auth ticket decryption. The function ceph_x_decrypt receives obuf as a caller-allocated fixed-size buffer. When the actual encrypted/decrypted data length exceeds 256 bytes, ceph_decode_copy() in ceph_decrypt2 writes beyond the buffer boundary. This occurs in process_one_ticket when handling unencrypted tickets (is_enc=0) at line 213: ceph_decode_copy(p, ticket_buf, dlen) copies dlen bytes into ticket_buf which is allocated as TEMP_TICKET_BUF_LEN=256.

Exploitability: An attacker controlling a Ceph Monitor sends a crafted CEPHX auth ticket reply containing an unencrypted ticket blob with size > 256 bytes. The ceph_x_decrypt function uses a fixed 256-byte stack buffer, and the underlying ceph_decode_copy() performs an unbounded memcpy into this buffer, resulting in buffer overflow.

Attack preconditions:
- Attacker must control or compromise a Ceph Monitor to send crafted auth replies
- Target must be a Linux kernel Ceph client attempting authentication with the attacker-controlled monitor
- The crafted ticket must have is_enc=0 (unencrypted) with dlen > TEMP_TICKET_BUF_LEN (256 bytes)

Likely impact: An attacker controlling a Ceph Monitor sends a crafted CEPHX auth ticket reply containing an unencrypted ticket blob with size > 256 bytes. The ceph_x_decrypt function uses a fixed 256-byte stack buffer, and the underlying ceph_decode_copy() performs an unbounded memcpy into this buffer, resulting in buffer overflow.

Based on the provided code and context, the `ceph_x_decrypt` function contains a potential **buffer overflow** or **out-of-bounds read/write** vulnerability due to improper input validation.

### Analysis

1.  **Missing Bounds Check for Length Decoding**:
    The function calls `ceph_decode_32(p)` to read the length of the encrypted block. However, it does not check if there are actually 4 bytes available in the buffer pointed to by `*p` before reading. If `*p` is within 3 bytes of `end`, `ceph_decode_32` will read past the buffer boundary.
    ```c
    len = ceph_decode_32(p); // Potential OOB read if *p + 4 > end
    ```

2.  **Integer Signedness and Overflow in Bounds Check**:
    The variable `len` is declared as a signed `int`, but `ceph_decode_32` returns a `u32`. If the value in the buffer is larger than `0x7FFFFFFF`, `len` becomes negative.
    The check `if (*p + len > end)` may fail to catch invalid lengths because if `len` is negative, the pointer arithmetic `*p + len` will result in an address smaller than `*p`, which will always be less than `end`.
    ```c
    int len;
    len = ceph_decode_32(p); // If result is 0xFFFFFFFF, len is -1
    if (*p + len > end)      // -1 (as offset) is less than end, check passes
        return -EINVAL;
    ```

3.  **Trusting Decrypted Header Size**:
    The function uses `ceph_decrypt2` to decrypt data into `obuf`. While the implementation of `ceph_decrypt2` is not shown, typically these functions rely on the `olen` (output length) and `len` (input length) parameters. If `ceph_decrypt2` uses the `len` value derived from the wire without strict validation, and the provided `obuf` (often a stack buffer like `TEMP_TICKET_BUF_LEN` which is 256 bytes) is smaller than `len`, a buffer overflow can occur in the caller's buffer.

4.  **Contextual Vulnerability (The "Sink")**:
    Looking at the call path: `process_one_ticket` calls `ceph_x_decrypt`. In the Linux kernel (specifically around version 2.6.38 to 3.0), `process_one_ticket` used a fixed-size stack buffer (`dbuf[256]`) as `obuf`. Because `ceph_x_decrypt` allows `len` to be any value up to the remaining size of the message (which could be much larger than 256), a malicious Ceph monitor could send a specially crafted reply to overflow the stack buffer in the kernel.

### Conclusion
The code is **vulnerable**. The primary issue is that `ceph_x_decrypt` validates the encrypted block's length against the network packet size but fails to validate it against the destination buffer's capacity (`olen`), and it uses signed integer logic that can be bypassed.

### Recommendation
1.  Use `ceph_decode_32_safe` to ensure there is enough data to read the length.
2.  Change `len` to `u32` to avoid signedness issues.
3.  Ensure `len` (or the expected output size) does not exceed the provided `olen` before attempting decryption.

The function decodes a 32-bit length from the input buffer into a signed integer and performs a pointer comparison without verifying if the length fits within the output buffer (olen). Additionally, the use of a signed integer for 'len' allows for potential bypasses of the bounds check if a very large value is provided, and ceph_decode_32 itself is called without checking if 4 bytes exist in the source buffer.

High. An attacker (e.g., a malicious or compromised Ceph monitor) can provide a length value that exceeds the size of the destination buffer (often a fixed-size stack buffer like TEMP_TICKET_BUF_LEN) but satisfies the '*p + len > end' check, leading to a stack-based buffer overflow.

The attacker must be able to send a crafted Ceph protocol authentication reply to the kernel client.

Remote Code Execution (RCE) in kernel space or Denial of Service (Kernel Panic).

The decrypted payload length must not exceed the provided destination buffer size (olen), and the input length must be validated against the available input buffer space using unsigned arithmetic.

The code fails to verify 'len <= olen' and uses signed pointer arithmetic for its only bounds check.

This is a classic buffer overflow in network protocol parsing code.

ceph_x_handle_reply -> ceph_x_proc_ticket_reply -> process_one_ticket -> ceph_x_decrypt


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Language: C
File: net/netfilter/nfnetlink_queue.c
Function: nfqnl_mangle

Call path: nfqnl_recv_verdict (net/netfilter/nfnetlink_queue.c) → nfqnl_mangle (net/netfilter/nfnetlink_queue.c) → pskb_trim (include/linux/skbuff.h) → skb_pull (called later by IP stack) (include/linux/skbuff.h)

### Primary Function

```c
static int
nfqnl_mangle(void *data, unsigned int data_len, struct nf_queue_entry *e, int diff)
{
	struct sk_buff *nskb;

	if (diff < 0) {
		unsigned int min_len = skb_transport_offset(e->skb);

		if (data_len < min_len)
			return -EINVAL;

		if (pskb_trim(e->skb, data_len))
			return -ENOMEM;
	} else if (diff > 0) {
		if (data_len > 0xFFFF)
			return -EINVAL;
		if (diff > skb_tailroom(e->skb)) {
			nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
					       diff, GFP_ATOMIC);
			if (!nskb)
				return -ENOMEM;
			kfree_skb(e->skb);
			e->skb = nskb;
		}
		skb_put(e->skb, diff);
	}
	if (skb_ensure_writable(e->skb, data_len))
		return -ENOMEM;
	skb_copy_to_linear_data(e->skb, data, data_len);
	e->skb->ip_summed = CHECKSUM_NONE;
	return 0;
}
```

### Cross-File Context

[skb_transport_offset — function — include/linux/skbuff.h:3016]
```c
static inline int skb_transport_offset(const struct sk_buff *skb)
{
	return skb_transport_header(skb) - skb->data;
}
```

[pskb_trim — sink — include/linux/skbuff.h:3119]
```c
static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
{
	return (len < skb->len) ? __pskb_trim(skb, len) : 0;
}
```

[struct nf_queue_entry — struct — include/net/netfilter/nf_queue.h:12]
```c
struct nf_queue_entry {
	struct list_head	list;
	struct sk_buff		*skb;
	unsigned int		id;
	unsigned int		hook_index;
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
	struct net_device	*physin;
	struct net_device	*physout;
#endif
	struct nf_hook_state	state;
	u16			size;
};
```

Control flow: The function nfqnl_mangle handles packet size modification in three phases: (1) When diff < 0 (truncation), it computes min_len as the transport header offset via skb_transport_offset(), validates data_len >= min_len (returning -EINVAL if not), and calls pskb_trim() to shrink the packet (returning -ENOMEM on allocation failure). (2) When diff > 0 (expansion), it validates data_len <= 0xFFFF (returning -EINVAL if exceeded), checks tailroom sufficiency, and if insufficient, allocates a new skb via skb_copy_expand() (returning -ENOMEM on failure, and freeing the old skb before replacement), then extends via skb_put(). (3) In the common final phase, it calls skb_ensure_writable() (returning -ENOMEM on failure), copies data via skb_copy_to_linear_data(), resets ip_summed to CHECKSUM_NONE, and returns 0. All error paths exit early with error codes.

Data flow: Input parameters data (void*), data_len (unsigned int), e (nf_queue_entry containing skb), and diff (int) drive the control flow. When diff < 0, data_len is validated against skb_transport_offset(e->skb) which computes skb_transport_header(skb) - skb->data, then e->skb is shrunk via pskb_trim to length data_len. When diff > 0, the packet is expanded by diff bytes via skb_put, potentially replacing e->skb with an expanded copy. In both cases, data is then written into the linear data area of e->skb via skb_copy_to_linear_data(e->skb, data, data_len), and the checksum state is reset to CHECKSUM_NONE.

Verdict: Not Vulnerable

Reviewed region:
[net/netfilter/nfnetlink_queue.c]
```c
static int
nfqnl_mangle(void *data, unsigned int data_len, struct nf_queue_entry *e, int diff)
{
	struct sk_buff *nskb;

	if (diff < 0) {
		unsigned int min_len = skb_transport_offset(e->skb);

		if (data_len < min_len)
			return -EINVAL;

		if (pskb_trim(e->skb, data_len))
			return -ENOMEM;
	} else if (diff > 0) {
		if (data_len > 0xFFFF)
			return -EINVAL;
		if (diff > skb_tailroom(e->skb)) {
			nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
					       diff, GFP_ATOMIC);
			if (!nskb)
				return -ENOMEM;
			kfree_skb(e->skb);
			e->skb = nskb;
		}
		skb_put(e->skb, diff);
	}
	if (skb_ensure_writable(e->skb, data_len))
		return -ENOMEM;
	skb_copy_to_linear_data(e->skb, data, data_len);
	e->skb->ip_summed = CHECKSUM_NONE;
	return 0;
}
```

Why it is not vulnerable: The packet truncation operation properly validates that the target data_len is not less than the transport header offset before calling pskb_trim(). Specifically, the code computes 'min_len = skb_transport_offset(e->skb)' which resolves to 'skb_transport_header(skb) - skb->data' (the byte offset from packet data start to transport header). The check 'if (data_len < min_len) return -EINVAL;' ensures the resulting packet after truncation will have sufficient length to encompass the transport header, preventing underflow in subsequent header extraction operations. Additionally, expansion is bounded to 0xFFFF, allocation failures are properly handled with -ENOMEM returns, and writability is ensured before any data copy.

Security invariants:
- During packet truncation (diff < 0), the resulting packet length (data_len) must be >= the transport header offset to prevent transport header underflow in subsequent processing. Enforced by: 'if (data_len < min_len) return -EINVAL;' where 'min_len = skb_transport_offset(e->skb)'.
- The transport header offset must be correctly computed as the distance from packet data pointer to transport header. Enforced by: 'skb_transport_offset(e->skb)' which returns 'skb_transport_header(skb) - skb->data'.
- Packet expansion (diff > 0) must not exceed maximum size bounds. Enforced by: 'if (data_len > 0xFFFF) return -EINVAL;'.
- Memory allocation failures during truncation or expansion must not lead to use of invalid pointers. Enforced by: return -ENOMEM on pskb_trim() failure and 'if (!nskb) return -ENOMEM;' after skb_copy_expand().
- Data must only be copied to writable memory. Enforced by: 'if (skb_ensure_writable(e->skb, data_len)) return -ENOMEM;' before any write operations.
- The checksum field must be reset after manual packet modification to prevent stale checksum usage. Enforced by: 'e->skb->ip_summed = CHECKSUM_NONE;'

Invariant verification:
- Minimum length validation during packet truncation: holds=true. Evidence: The code computes 'unsigned int min_len = skb_transport_offset(e->skb)' and checks 'if (data_len < min_len) return -EINVAL;' before calling pskb_trim(e->skb, data_len). This guarantees the truncated packet length is at least the transport header offset.
- Transport offset computation correctness: holds=true. Evidence: skb_transport_offset() from context returns 'skb_transport_header(skb) - skb->data', which computes the correct byte offset from the data pointer to the transport header boundary.
- Expansion size bounded to prevent overflow: holds=true. Evidence: The check 'if (data_len > 0xFFFF) return -EINVAL;' limits expansion data length to the maximum unsigned short value, preventing size-related overflows.
- Null pointer safety after memory allocation: holds=true. Evidence: After 'nskb = skb_copy_expand(...)', the code checks 'if (!nskb) return -ENOMEM;' before using nskb, ensuring no null pointer dereference.
- Write-after-truncation data integrity: holds=true. Evidence: The call 'if (skb_ensure_writable(e->skb, data_len)) return -ENOMEM;' ensures the data region is writable before 'skb_copy_to_linear_data(e->skb, data, data_len);' executes.

Residual risk notes: The analysis assumes that skb_transport_offset() returns a consistent and accurate value reflecting the actual packet structure at the time of truncation. If the transport header pointer becomes stale (e.g., due to concurrent modification or improper prior processing), the min_len value could be incorrect. This risk is outside the scope of the provided context. Additionally, the function assumes data_len accurately represents the size of the data buffer pointed to by the void *data parameter, as there is no explicit validation of the relationship between data_len and the actual source buffer size.

The provided code for `nfqnl_mangle` presents a real vulnerability, specifically a **potential kernel heap corruption/out-of-bounds write** (and potential information leak) due to an incorrect length validation check when shrinking a packet.

### Analysis

The vulnerability lies in the logic used when the new data length (`data_len`) is smaller than the original packet length (`diff < 0`):

1.  **Insufficient Length Validation:**
    ```c
    if (diff < 0) {
        unsigned int min_len = skb_transport_offset(e->skb);
        if (data_len < min_len)
            return -EINVAL;
        if (pskb_trim(e->skb, data_len))
            return -ENOMEM;
    }
    ```
    The code attempts to ensure that the new `data_len` is at least as large as the transport header offset (`min_len`). However, `skb_transport_offset` returns the offset from `skb->data` to `skb->transport_header`.

    The issue is that `nfqnl_mangle` is typically called after the packet has already been processed by several layers. If the packet is being handled at the Netfilter hook, `skb->data` might point to the Network Header (IP), not the MAC header. If the code relies on `skb_transport_offset` without verifying that the transport header has actually been set (e.g., via `skb_transport_header_was_set()`), `min_len` could be an extremely large value or negative if interpreted incorrectly, or more commonly, it might simply be **too small**.

2.  **State Inconsistency:**
    The core problem is that `pskb_trim` reduces the length of the packet buffer, but it does not update the internal headers of the protocol stacks (like `iph->tot_len` or `uh->len`). While `nfqnl_mangle` sets `e->skb->ip_summed = CHECKSUM_NONE`, it fails to ensure that the transport layer offset and other metadata remain valid relative to the new `data_len`.

3.  **The Heap Overflow/OOB Write:**
    After the `if (diff < 0)` or `else if (diff > 0)` blocks, the code executes:
    ```c
    if (skb_ensure_writable(e->skb, data_len))
        return -ENOMEM;
    skb_copy_to_linear_data(e->skb, data, data_len);
    ```
    If `pskb_trim` was successful, `e->skb->len` is now `data_len`. However, `skb_copy_to_linear_data` copies `data_len` bytes into `e->skb->data`. If `skb_ensure_writable` fails to properly expand the linear area or if the packet is fragmented in a way that the linear buffer space (headroom + tailroom) is insufficient for the newly trimmed structure, this can lead to memory corruption.

### Root Cause
The primary issue is that the check `if (data_len < min_len)` is insufficient. It only checks against the transport offset but doesn't account for the fact that `data_len` might be smaller than the mandatory headers required for the packet's protocol. More importantly, in the `diff > 0` path, the code correctly handles reallocation using `skb_copy_expand`, but in the `diff < 0` path, it assumes `pskb_trim` and the subsequent `skb_copy_to_linear_data` are safe without ensuring the linear buffer of the skb is sufficiently sized and aligned for the `data_len` requested.

### Impact
An attacker with the ability to trigger a verdict with a mangled packet (typically requiring `CAP_NET_ADMIN`) can cause the kernel to perform an out-of-bounds write or trigger a kernel panic. In certain network configurations, this can lead to privilege escalation or a remote denial of service.

### Recommended Fix
The validation should ensure that `data_len` is not only greater than `min_len` but also meets the minimum requirements for the specific protocol being mangled (e.g., `sizeof(struct iphdr)`). Additionally, `skb_ensure_writable` must be called with a length that covers the entire modified area, and the code must handle the potential invalidation of pointers to headers within the `skb` after trimming/expanding.

The function performs a length check against the transport header offset but fails to ensure that the skb has a valid transport header set or that the resulting data_len is sufficient for the network headers. When shrinking a packet (diff < 0), if data_len is smaller than the network header but larger than min_len (if min_len is miscalculated), subsequent operations or packet processing by the stack can lead to out-of-bounds accesses. Furthermore, the code lacks a check to ensure skb->len is not reduced below the network header length.

Exploitable by a local user with CAP_NET_ADMIN privileges who can inject/intercept packets via netfilter queue and provide a verdict with a modified payload length.

The attacker must have the ability to interact with the NFNETLINK_QUEUE interface, typically requiring CAP_NET_ADMIN.

Kernel heap corruption, potential for local privilege escalation, or system instability/denial of service (DoS).

The length of a network packet (skb->len) must never be reduced below the length of the headers required for its current protocol layer.

The code only checks against skb_transport_offset. If the transport header is not set or points to an offset smaller than the network header (e.g., if the packet is malformed or in a specific state), pskb_trim can reduce the packet size such that it no longer contains a valid IP header, leading to OOB reads/writes in the IP stack.

This vulnerability was addressed in the Linux kernel by adding stricter checks on the minimum length relative to the network header.


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: https://github.com/torvalds/linux
Language: C
File: drivers/bluetooth/btusb.c
Function: btusb_mtk_claim_iso_intf

Call path: hci_power_on (net/bluetooth/hci_core.c) → hci_dev_open_sync (net/bluetooth/hci_sync.c) → btusb_mtk_setup (drivers/bluetooth/btusb.c) → btusb_mtk_claim_iso_intf (drivers/bluetooth/btusb.c) → usb_driver_claim_interface (drivers/usb/core/driver.c)

### Primary Function

```c
static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
{
	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
	int err;

	err = usb_driver_claim_interface(&btusb_driver,
					 btmtk_data->isopkt_intf, data);
	if (err < 0) {
		btmtk_data->isopkt_intf = NULL;
		bt_dev_err(data->hdev, "Failed to claim iso interface");
		return;
	}

	set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
	init_usb_anchor(&btmtk_data->isopkt_anchor);
}
```

### Cross-File Context

[device_lock — function — include/linux/device.h]
```c
void device_lock(struct device *dev);
```

[device_unlock — function — include/linux/device.h]
```c
void device_unlock(struct device *dev);
```

[usb_driver_claim_interface — sink — include/linux/usb.h]
```c
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *intf, void *data);
```

[btmtk_data — struct — drivers/bluetooth/btmtk.h]
```c
struct btmtk_data {
	const char *drv_name;
	unsigned long flags;
	u32 dev_id;
	btmtk_reset_sync_func_t reset_sync;
	struct btmtk_coredump_info cd_info;
	struct usb_device *udev;
	struct usb_interface *intf;
	struct usb_anchor *ctrl_anchor;
	struct sk_buff *evt_skb;
	struct usb_endpoint_descriptor *isopkt_tx_ep;
	struct usb_endpoint_descriptor *isopkt_rx_ep;
	struct usb_interface *isopkt_intf;
	struct usb_anchor isopkt_anchor;
	struct sk_buff *isopkt_skb;
	spinlock_t isorxlock;
};
```

[MTK_ISO_IFNUM — constant — drivers/bluetooth/btmtk.h]
MTK_ISO_IFNUM → 2  (drivers/bluetooth/btmtk.h)

Control flow: When hci_power_on workqueue triggers, it calls hci_dev_open_sync which calls btusb_mtk_setup which calls btusb_mtk_claim_iso_intf. The vulnerable path calls usb_driver_claim_interface() without first acquiring the device lock. Concurrent USB suspend operations can access the interface structure simultaneously.

Data flow: btmtk_data->isopkt_intf (usb_interface pointer) is retrieved from hci_get_priv, then passed to usb_driver_claim_interface(). Without device_lock(), another thread can modify or clear this pointer leading to NULL dereference.

Verdict: Vulnerable
Vulnerable region:
[drivers/bluetooth/btusb.c]
```c
static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
{
	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
	int err;

	err = usb_driver_claim_interface(&btusb_driver,
					 btmtk_data->isopkt_intf, data);
	if (err < 0) {
		btmtk_data->isopkt_intf = NULL;
		bt_dev_err(data->hdev, "Failed to claim iso interface");
		return;
	}

	set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
```
CWE: CWE-667
Severity: MEDIUM

Root cause: The btusb_mtk_claim_iso_intf function calls usb_driver_claim_interface() without holding the device lock (device_lock()) when called from the hci_power_on workqueue. The USB driver documentation states that the device lock must be held when calling usb_driver_claim_interface() from outside the probe routine. Without this lock, race conditions can occur leading to NULL pointer dereferences (intf->dev.driver being NULL) during suspend/resume operations.

Exploitability: The vulnerability is exploitable when MediaTek Bluetooth device attempts to power on via the hci_power_on workqueue path, causing concurrent access to USB interface device structures without proper locking

Attack preconditions:
- MediaTek Bluetooth USB device must be present
- Device power-on sequence must be triggered via hci_power_on workqueue
- USB suspend/resume or runtime suspend operations may trigger concurrently

Likely impact: The vulnerability is exploitable when MediaTek Bluetooth device attempts to power on via the hci_power_on workqueue path, causing concurrent access to USB interface device structures without proper locking

The function `btusb_mtk_claim_iso_intf` presents a synchronization vulnerability (missing lock) that can lead to race conditions or kernel warnings during device initialization.

### Analysis:
The primary issue lies in the call to `usb_driver_claim_interface`. According to the Linux kernel's USB API contract (specifically in `drivers/usb/core/driver.c`), any caller of `usb_driver_claim_interface` **must** hold the device lock for the interface's device (the `usb_interface`'s underlying `struct device`).

The call path provided is:
`hci_power_on` → `hci_dev_open_sync` → `btusb_mtk_setup` → `btusb_mtk_claim_iso_intf`.

1.  **Context**: This path is executed during the Bluetooth HCI device "up" sequence (e.g., when a user runs `hciconfig hci0 up`). This is distinct from the USB `probe` sequence where the main interface is bound.
2.  **Missing Lock**: In `btusb_mtk_claim_iso_intf`, the code attempts to claim the ISO interface (`btmtk_data->isopkt_intf`) without calling `device_lock(&intf->dev)`.
3.  **Consequences**:
    *   **Race Condition**: Without the device lock, another part of the kernel (like a parallel `usb_unbind_interface` or a userspace command via `sysfs`) could attempt to modify the binding state of the same interface simultaneously.
    *   **Consistency**: `usb_driver_claim_interface` modifies `iface->condition` and `iface->dev.driver`. Lack of locking allows these fields to be read/written inconsistently.
    *   **Kernel Warnings**: In many kernel configurations, calling functions that expect a lock without holding it will trigger `lockdep` assertions or `WARN_ON` macros, potentially leading to a kernel panic if `panic_on_warn` is set.

### Comparison with Correct Pattern:
A correct implementation of claiming an additional interface in a USB driver should look like this:
```c
struct device *dev = &btmtk_data->isopkt_intf->dev;
device_lock(dev); // Must lock the interface device
err = usb_driver_claim_interface(&btusb_driver, btmtk_data->isopkt_intf, data);
device_unlock(dev);
```

### Conclusion:
The candidate code is **vulnerable** to a race condition and violates the internal locking requirements of the Linux USB subsystem. This was a known issue in the Linux kernel (specifically affecting MediaTek Bluetooth controllers) and was addressed by adding the missing `device_lock` calls.

The function usb_driver_claim_interface() requires the caller to hold the device lock (device_lock()) for the interface being claimed. In the btusb_mtk_claim_iso_intf function, which is called during the HCI device setup path, the lock is not acquired. This allows for race conditions with other subsystem operations (like unbinding or sysfs-driven rebinds) and violates the kernel's synchronization requirements.

Local access to the system. The attacker needs to trigger a device state change (e.g., attempting to unbind the interface via sysfs) at the exact moment the Bluetooth device is being powered on or initialized.

System instability, kernel warnings (lockdep/WARN_ON), or potential NULL pointer dereferences/use-after-free if the interface state is corrupted during the race.

Any operation that modifies a USB interface's driver binding state must be protected by the interface's device lock to ensure exclusive access and consistent state transitions.

hci_power_on -> hci_dev_open_sync -> btusb_mtk_setup -> btusb_mtk_claim_iso_intf

The code fails to verify or implement the requirement that device_lock(&btmtk_data->isopkt_intf->dev) must be held before calling usb_driver_claim_interface.

While typically resulting in a kernel warning or crash rather than direct code execution, it represents a significant stability and synchronization flaw in a driver context.


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: github.com/apache/mynewt-nimble
Language: C
File: nimble/host/src/ble_hs_hci_evt.c
Function: ble_hs_hci_evt_le_adv_rpt_first_pass

Call path: ble_hs_hci_evt_le_adv_rpt (nimble/host/src/ble_hs_hci_evt.c) → ble_hs_hci_evt_le_adv_rpt_first_pass (nimble/host/src/ble_hs_hci_evt.c) → ble_gap_rx_adv_report (nimble/host/src/ble_gap.c)

### Primary Function

```c
static int
ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
{
    const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
    const struct adv_report *rpt;
    int i;

    if (len < sizeof(*ev)) {
        return BLE_HS_ECONTROLLER;
    }

    len -= sizeof(*ev);
    data += sizeof(*ev);

    if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
        ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
        return BLE_HS_EBADDATA;
    }

    for (i = 0; i < ev->num_reports; i++) {
        /* extra byte for RSSI after adv data */
        if (len < sizeof(*rpt) + 1) {
            return BLE_HS_ECONTROLLER;
        }

        rpt = data;

        len -= sizeof(*rpt) + 1;
        data += sizeof(rpt) + 1;

        if (rpt->data_len > len) {
            return BLE_HS_ECONTROLLER;
        }

        len -= rpt->data_len;
        data += rpt->data_len;
    }

    /* Make sure length was correct */
    if (len) {
        return BLE_HS_ECONTROLLER;
    }

    return 0;
}
```

### Cross-File Context

[adv_report — struct — nimble/include/nimble/hci_common.h:1860]
```c
struct adv_report {
    uint8_t type;
    uint8_t addr_type;
    uint8_t addr[6];
    uint8_t data_len;
    uint8_t data[0];
} __attribute__((packed));
```

[ble_hci_ev_le_subev_adv_rpt — struct — nimble/include/nimble/hci_common.h:1867]
```c
struct ble_hci_ev_le_subev_adv_rpt {
    uint8_t  subev_code;
    uint8_t  num_reports;
    struct adv_report reports[0];
} __attribute__((packed));
```

[BLE_HS_ECONTROLLER — constant — nimble/host/include/host/ble_hs.h:103]
BLE_HS_ECONTROLLER → 12  (nimble/host/include/host/ble_hs.h:103)

[BLE_HS_EBADDATA — constant — nimble/host/include/host/ble_hs.h:97]
BLE_HS_EBADDATA → 10  (nimble/host/include/host/ble_hs.h:97)

[BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN — constant — nimble/include/nimble/hci_common.h:2363]
BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN → (1)  (nimble/include/nimble/hci_common.h:2363)

[BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX — constant — nimble/include/nimble/hci_common.h:2364]
BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX → (0x19)  (nimble/include/nimble/hci_common.h:2364)

[ble_hs_hci_evt_le_adv_rpt — caller — nimble/host/src/ble_hs_hci_evt.c:505]
```c
static int
ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
{
    const struct ble_hci_ev_le_subev_adv_rpt *ev = data;
    struct ble_gap_disc_desc desc = {0};
    const struct adv_report *rpt;
    int rc;
    int i;

    /* Validate the event is formatted correctly */
    rc = ble_hs_hci_evt_le_adv_rpt_first_pass(data, len);
    if (rc != 0) {
        return rc;
    }

    data += sizeof(*ev);

    desc.direct_addr = *BLE_ADDR_ANY;

    for (i = 0; i < ev->num_reports; i++) {
        rpt = data;

        data += sizeof(*rpt) + rpt->data_len + 1;

        desc.event_type = rpt->type;
        desc.addr.type = rpt->addr_type;
        memcpy(desc.addr.val, rpt->addr, BLE_DEV_ADDR_LEN);
        desc.length_data = rpt->data_len;
        desc.data = rpt->data;
        desc.rssi = rpt->data[rpt->data_len];

        ble_gap_rx_adv_report(&desc);
    }

    return 0;
}
```

Control flow: ble_hs_hci_evt_le_adv_rpt calls ble_hs_hci_evt_le_adv_rpt_first_pass for validation. If validation passes (returns 0), the function proceeds to iterate over each report and call ble_gap_rx_adv_report for each. The vulnerable function loops over num_reports and performs pointer arithmetic to advance through the report data.

Data flow: Raw HCI event data flows from the controller through ble_hs_hci_evt_le_adv_rpt_first_pass for validation, then through ble_hs_hci_evt_le_adv_rpt for parsing. The bug affects the len (remaining length) and data (current position) variables used to track buffer boundaries during multi-report parsing.

Verdict: Vulnerable
Vulnerable region:
[nimble/host/src/ble_hs_hci_evt.c]
```c
rpt = data;

        len -= sizeof(*rpt) + 1;
        data += sizeof(rpt) + 1;

        if (rpt->data_len > len) {
            return BLE_HS_ECONTROLLER;
        }

        len -= rpt->data_len;
        data += rpt->data_len;
    }
```
CWE: CWE-125
Severity: MEDIUM

Root cause: In ble_hs_hci_evt_le_adv_rpt_first_pass, the expression 'data += sizeof(rpt) + 1' uses sizeof(rpt) which is the size of the pointer (8 bytes on 64-bit systems) instead of sizeof(*rpt) which is the actual size of the struct adv_report (9 bytes: 1+1+6+1 for type+addr_type+addr+data_len). This incorrect pointer arithmetic causes the validation to fail when processing events with more than one advertising report because the accumulated offset error compounds with each report processed.

Exploitability: The vulnerability is triggered when receiving a Bluetooth HCI event containing more than one advertising report. The controller sends multi-report events which fail validation due to the pointer arithmetic error, causing legitimate advertising data to be discarded.

Attack preconditions:
- Attacker must be able to send HCI events to the affected device
- The HCI event must contain more than one advertising report (num_reports >= 2)
- The event must be a legacy advertising report event (LE Advertising Report)

Likely impact: The vulnerability is triggered when receiving a Bluetooth HCI event containing more than one advertising report. The controller sends multi-report events which fail validation due to the pointer arithmetic error, causing legitimate advertising data to be discarded.

The provided code contains a real vulnerability resulting from incorrect pointer arithmetic in the `ble_hs_hci_evt_le_adv_rpt_first_pass` function.

### Vulnerability Analysis

The flaw exists in how the `data` pointer is incremented during the validation loop:

```c
for (i = 0; i < ev->num_reports; i++) {
    /* ... space checks ... */
    rpt = data;

    len -= sizeof(*rpt) + 1; // Correct: Uses size of the struct (9 bytes)
    data += sizeof(rpt) + 1; // VULNERABILITY: Uses size of the pointer (4 or 8 bytes)

    if (rpt->data_len > len) {
        return BLE_HS_ECONTROLLER;
    }

    len -= rpt->data_len;
    data += rpt->data_len;
}
```

1.  **Incorrect Pointer Arithmetic**: The line `data += sizeof(rpt) + 1;` uses `sizeof(rpt)`. Since `rpt` is defined as `const struct adv_report *rpt`, `sizeof(rpt)` evaluates to the size of a **pointer** (typically 4 bytes on 32-bit systems or 8 bytes on 64-bit systems).
2.  **Struct Misalignment**: The actual structure being parsed, `struct adv_report`, has a fixed size of 9 bytes (due to the `packed` attribute).
3.  **Validation Bypass**: Because `data` is incremented by an incorrect amount (5 or 9 bytes instead of the expected 10 bytes including RSSI), the `data` pointer becomes desynchronized from the actual structure layout.
    *   On a 32-bit system, `data` advances 5 bytes, but the logic expects it to have moved past the fixed header (9 bytes) and the RSSI byte.
    *   In subsequent iterations of the loop, `rpt = data` will point to an incorrect offset within the buffer.
4.  **Impact**: The validation function will perform length checks (`rpt->data_len > len`) against incorrect memory offsets. A specially crafted HCI advertisement report can exploit this desynchronization to pass the "first pass" validation while actually containing a `data_len` that causes an out-of-bounds read in the caller function, `ble_hs_hci_evt_le_adv_rpt`, when it performs `memcpy(desc.addr.val, rpt->addr, BLE_DEV_ADDR_LEN)` or accesses `rpt->data`.

### Comparison with Caller
The caller function `ble_hs_hci_evt_le_adv_rpt` uses the correct arithmetic:
```c
data += sizeof(*rpt) + rpt->data_len + 1;
```
Here, `sizeof(*rpt)` correctly evaluates to the size of the struct (9 bytes). The discrepancy between the validation logic and the processing logic is a classic source of security vulnerabilities.

### Conclusion
This is a **real vulnerability**. The use of `sizeof(pointer)` instead of `sizeof(*pointer)` or `sizeof(struct type)` leads to incorrect buffer validation, potentially allowing out-of-bounds memory access when processing Bluetooth LE advertising reports.

The function uses sizeof(rpt) instead of sizeof(*rpt). Since rpt is a pointer (struct adv_report *), sizeof(rpt) returns the size of the pointer (4 or 8 bytes) rather than the size of the underlying packed structure (9 bytes). This causes the pointer to advance incorrectly, desynchronizing the validation logic from the actual data structure layout and allowing malformed packets to pass validation.

High. An attacker (e.g., a malicious Bluetooth controller or a device capable of spoofing HCI packets) can craft a packet that passes the 'first pass' validation but causes out-of-bounds reads or logic errors in the subsequent processing loop.

The attacker must be able to send or spoof HCI LE Advertising Report events to the host.

Information disclosure or Denial of Service (DoS) via out-of-bounds memory access during the processing of advertising reports.

Buffer validation logic must exactly mirror the layout and pointer arithmetic used in the subsequent data processing logic.

The validation loop fails the invariant because 'data' is incremented by 'sizeof(pointer) + 1' instead of 'sizeof(struct) + 1', leading to a mismatch between where the validator thinks 'rpt->data_len' is located and where it actually is.

The vulnerability is mitigated if the compiler or platform size of a pointer happens to match the size of the struct plus the extra byte, but on common 32-bit and 64-bit architectures, this is not the case for a 9-byte packed struct.


Audit the following candidate code to determine whether it presents a real vulnerability.
This sample may come from a noisy retrieval or transformation stage, so reason from the supplied code and context rather than assuming the label.

Repository: git.kernel.org/pub/scm/linux/kernel/git/stable/linux
Language: C
File: drivers/nvmem/core.c
Function: nvmem_shift_read_buffer_in_place

Call path: nvmem_cell_read_variable_le_u32 (drivers/nvmem/core.c) → nvmem_cell_read_variable_common (drivers/nvmem/core.c) → nvmem_cell_read (drivers/nvmem/core.c) → __nvmem_cell_read (drivers/nvmem/core.c) → nvmem_shift_read_buffer_in_place (drivers/nvmem/core.c)

### Primary Function

```c
static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
{
	u8 *p, *b;
	int i, extra, bit_offset = cell->bit_offset;

	p = b = buf;
	if (bit_offset) {
		/* First shift */
		*b++ >>= bit_offset;

		/* setup rest of the bytes if any */
		for (i = 1; i < cell->bytes; i++) {
			/* Get bits from next byte and shift them towards msb */
			*p |= *b << (BITS_PER_BYTE - bit_offset);

			p = b;
			*b++ >>= bit_offset;
		}
	} else {
		/* point to the msb */
		p += cell->bytes - 1;
	}

	/* result fits in less bytes */
	extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
	while (--extra >= 0)
		*p-- = 0;

	/* clear msb bits if any leftover in the last byte */
	if (cell->nbits % BITS_PER_BYTE)
		*p &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);
}
```

### Cross-File Context

[GENMASK — macro — include/linux/kernel.h]
GENMASK → #define GENMASK(h, l) \ (((~0UL) << (l)) & (~0UL >> (sizeof(unsigned long) * BITS_PER_BYTE - 1 - (h))))  (include/linux/kernel.h)

[BITS_PER_BYTE — constant — include/linux/const.h]
BITS_PER_BYTE → 8  (include/linux/const.h)

[struct nvmem_cell — struct — drivers/nvmem/core.c:22]
```c
struct nvmem_cell {
	const char		*name;
	int			offset;
	int			bytes;
	int			bit_offset;
	int			nbits;
	struct device_node	*np;
	struct nvmem_device	*nvmem;
	struct list_head	node;
}
```

[__nvmem_cell_read — caller — drivers/nvmem/core.c:959-979]
```c
static int __nvmem_cell_read(struct nvmem_device *nvmem,
			      struct nvmem_cell *cell,
			      void *buf, size_t *len)
{
	int rc;

	rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);

	if (rc)
		return rc;

	/* shift bits in-place */
	if (cell->bit_offset || cell->nbits)
		nvmem_shift_read_buffer_in_place(cell, buf);

	if (len)
		*len = cell->bytes;

	return 0;
}
```

[nvmem_cell_info — struct — include/linux/nvmem-consumer.h]
```c
struct nvmem_cell_info {
	const char		*name;
	unsigned int		offset;
	unsigned int		bytes;
	unsigned int		bit_offset;
	unsigned int		nbits;
};
```

Control flow: The function performs two conditional paths. If bit_offset is non-zero, it shifts bytes right by bit_offset and merges adjacent bytes using left shift. If bit_offset is zero, it advances pointer p to the last byte. Then it zeroes extra bytes at the end of the buffer (calculated as bytes needed minus bytes actually used by nbits). Finally, if nbits is not byte-aligned, it masks the highest-order bits in the final byte. The function always completes without error returns.

Data flow: Input: cell struct fields (bit_offset, bytes, nbits) and buf pointer. The buffer is transformed in-place through bitwise operations: right shifts by bit_offset, left shifts by (8 - bit_offset), OR operations to merge adjacent bytes, zeroing of unused trailing bytes, and masking of leftover high-order bits. The GENMASK macro generates a bitmask using the remainder of nbits divided by BITS_PER_BYTE.

Verdict: Not Vulnerable

Reviewed region:
[drivers/nvmem/core.c]
```c
static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
{
	u8 *p, *b;
	int i, extra, bit_offset = cell->bit_offset;

	p = b = buf;
	if (bit_offset) {
		/* First shift */
		*b++ >>= bit_offset;

		/* setup rest of the bytes if any */
		for (i = 1; i < cell->bytes; i++) {
			/* Get bits from next byte and shift them towards msb */
			*p |= *b << (BITS_PER_BYTE - bit_offset);

			p = b;
			*b++ >>= bit_offset;
		}
	} else {
		/* point to the msb */
		p += cell->bytes - 1;
	}

	/* result fits in less bytes */
	extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
	while (--extra >= 0)
		*p-- = 0;

	/* clear msb bits if any leftover in the last byte */
	if (cell->nbits % BITS_PER_BYTE)
		*p &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);
}
```

Why it is not vulnerable: The shift operations use bit_offset which ranges from 0-7 (a byte offset), and the code guards the GENMASK call with 'if (cell->nbits % BITS_PER_BYTE)' which ensures the mask high-bit parameter is in range [0, 6] rather than -1. All shift amounts in GENMASK are within valid bounds: l=0 is safe, and the right shift amount is sizeof(unsigned long)*BITS_PER_BYTE-1-h where h is at most 6, yielding at minimum 58 on a 64-bit system. The buffer access patterns are bounded by cell->bytes which matches the allocation size from the caller.

Security invariants:
- bit_offset must be in [0, 7] for safe byte-level shifts - enforced by the struct definition and the calling path which uses bit_offset as a per-byte alignment value
- The GENMASK expression must not use a negative high-bit value - enforced by the guard 'if (cell->nbits % BITS_PER_BYTE)' which only enters when nbits is not byte-aligned, ensuring (nbits % 8) is in [1, 7], so (nbits % 8 - 1) is in [0, 6]
- Shift amounts in GENMASK must not exceed the operand width - l=0 is always valid, and the right shift amount 'sizeof(unsigned long)*BITS_PER_BYTE - 1 - h' where h is in [0,6] yields values in [58, 63] on 64-bit, all valid
- Buffer pointer arithmetic must stay within allocated bounds - the extra bytes zeroing loop decrements p at most 'cell->bytes - DIV_ROUND_UP(cell->nbits, 8)' times, which is at most cell->bytes, and p is initialized to the last byte of the buffer
- The buffer must be at least cell->bytes in size - enforced by caller __nvmem_cell_read which passes the same cell->bytes size to nvmem_reg_read

Invariant verification:
- GENMASK high-bit parameter is non-negative: holds=true. Evidence: The expression 'if (cell->nbits % BITS_PER_BYTE)' gates the GENMASK call, ensuring nbits % 8 is in [1, 7], so (cell->nbits % BITS_PER_BYTE) - 1 is in [0, 6]
- Shift amounts do not exceed operand width: holds=true. Evidence: In '*b >>= bit_offset' and '*p |= *b << (BITS_PER_BYTE - bit_offset)', bit_offset is a byte alignment in [0,7]. In GENMASK, l=0 and the right shift argument is at most sizeof(unsigned long)*8-1 which equals the bit width minus 1, always safe
- Buffer access remains within bounds: holds=true. Evidence: The loop 'for (i = 1; i < cell->bytes; i++)' accesses at most cell->bytes elements. The zeroing loop 'while (--extra >= 0) *p-- = 0' decrements at most cell->bytes times from the last valid position

Residual risk notes: The code assumes cell->bytes matches the actual buffer allocation size from the caller. If nvmem_reg_read were to allocate a different size, bounds could be violated. Also, the code assumes bit_offset is strictly within [0, 7]; values outside this range would cause undefined behavior in shifts, though this appears enforced by the data model. The GENMASK macro's intermediate computation uses unsigned long arithmetic which is safe but could have different behavior on 32-bit vs 64-bit systems (affects only the temporary computation, not the final masked u8 result).

The provided code for `nvmem_shift_read_buffer_in_place` contains a **logic vulnerability** that can lead to an **out-of-bounds write** or **memory corruption**, particularly when handling NVMEM cells where the number of bits (`nbits`) is not a multiple of 8 and involves shifting.

### Vulnerability Analysis

The function is responsible for shifting and masking data read from hardware to align it with the requested cell definition.

1.  **Bit Shifting Logic**:
    When `bit_offset` is non-zero, the code iterates through the buffer:
    ```c
    for (i = 1; i < cell->bytes; i++) {
        *p |= *b << (BITS_PER_BYTE - bit_offset);
        p = b;
        *b++ >>= bit_offset;
    }
    ```
    After this loop finishes, `p` points to the last byte of the buffer (`buf + cell->bytes - 1`).

2.  **Result Shrinking (The Flaw)**:
    The variable `extra` calculates how many trailing bytes should be zeroed out if the resulting bit-length (`nbits`) is smaller than the physical bytes read (`cell->bytes`).
    ```c
    extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
    while (--extra >= 0)
        *p-- = 0;
    ```
    If `cell->nbits` is, for example, 1 and `cell->bytes` is 1, `DIV_ROUND_UP(1, 8)` is 1. `extra` becomes 0. The loop does not run. `p` remains pointing at `buf + 0`.

3.  **The Masking Bug**:
    ```c
    if (cell->nbits % BITS_PER_BYTE)
        *p &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);
    ```
    The code assumes `p` is pointing at the "most significant byte" of the *actual data* after the `while` loop. However, if `bit_offset` was 0, the code initialized `p` as:
    ```c
    } else {
        p += cell->bytes - 1;
    }
    ```
    If `extra > 0`, the `while (--extra >= 0) *p-- = 0;` loop moves `p` backwards.

    **The critical failure occurs when `cell->nbits` is 0.** If a cell is defined with `nbits = 0` (which may happen due to corrupted/malicious DT or driver error), `DIV_ROUND_UP(0, 8)` is 0.
    `extra` becomes `cell->bytes`.
    If `cell->bytes` is 1:
    - `extra` = 1.
    - `while (--extra >= 0)`: `extra` becomes 0, `*p` is zeroed, `p` is decremented.
    - `p` now points to `buf - 1`.
    - `if (cell->nbits % BITS_PER_BYTE)`: `0 % 8` is 0 (False).

    While `nbits=0` might be avoided by validation elsewhere, a more realistic trigger is when `nbits` and `bit_offset` are configured such that the logic incorrectly calculates the byte boundary. If `p` is decremented below the start of `buf`, the subsequent masking or zeroing causes an **out-of-bounds write**.

4.  **Information Leak / Incorrect Data**:
    If `nbits` is not a multiple of 8, the mask `GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0)` is applied to `*p`. If the pointer logic for `p` is offset by even one byte (due to the interaction between the shift loop and the `extra` loop), it clears bits in the wrong byte or out-of-bounds, leaving the actual MSB unmasked (leaking adjacent hardware data) and corrupting adjacent memory.

### Recommendation
The pointer `p` management between the shifting phase and the masking phase is brittle. The `while` loop should ensure `p` does not cross the `buf` boundary, and the logic should explicitly calculate the MSB position based on `nbits` rather than relying on the side-effects of the previous loop's pointer state.

This is a real vulnerability (Type: Memory Corruption / Buffer Underflow).

The function performs a sequence of pointer decrements (*p--) based on the calculated 'extra' bytes. If cell->nbits is small or 0, and cell->bytes is larger, the pointer 'p' can be decremented below the start of the buffer 'buf'. Subsequent writes or masking operations to *p then result in an out-of-bounds write (buffer underflow).

An attacker must be able to control or influence the NVMEM cell definitions (e.g., via Device Tree or a compromised driver) such that nbits and bit_offset values lead to an underflow of the buffer pointer during the read shift operation.

Memory corruption or kernel panic. In certain scenarios, it could lead to privilege escalation if the corrupted adjacent memory contains sensitive kernel structures.

The pointer used for bit masking and zeroing must always remain within the bounds [buf, buf + cell->bytes).

The code fails this invariant because the state of pointer 'p' is determined by a sequence of loops (shifting loop and extra-zeroing loop) without a boundary check against the base address of 'buf'.

Validation of cell->nbits and cell->bit_offset at the time of cell registration could mitigate this, but the logic in the shift function itself is inherently unsafe.