Skip to content

Commit 01c0056

Browse files
committed
ASoC: apple: aop: Ensure all fields are aligned
Using unaligned fields with pin_init is unsound. Work around this by adjusting layout and packing of the structs. AudioSetDeviceProp downgraded `len` to u32. u64 based size appears improbable for audio device properties. PDMConfig rqeuried the most extinsive changes. Its size was padded with an extra byte to a multiple of 4. It contains multiple unaligned u32s which where replaced ith U32. Link: https://lore.kernel.org/rust-for-linux/20260228113713.1402110-1-lossin@kernel.org/ Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 1c57948 commit 01c0056

1 file changed

Lines changed: 42 additions & 25 deletions

File tree

sound/soc/apple/aop_audio.rs

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl AudioAttachDevice {
113113
}
114114
}
115115

116-
#[repr(C, packed)]
116+
#[repr(C, packed(4))]
117117
#[derive(Clone, Copy, Default)]
118118
struct LpaiChannelConfig {
119119
unk1: u32,
@@ -122,7 +122,7 @@ struct LpaiChannelConfig {
122122
unk4: u32,
123123
}
124124

125-
#[repr(C, packed)]
125+
#[repr(C, packed(4))]
126126
#[derive(Debug, Copy, Clone)]
127127
struct PDMConfig {
128128
bytes_per_sample: u32,
@@ -139,21 +139,26 @@ struct PDMConfig {
139139
ratio2: u8,
140140
ratio3: u8,
141141
_pad0: u8,
142-
filter_lengths: u32,
143-
coeff_bulk: u32,
142+
filter_lengths: U32,
143+
coeff_bulk: U32,
144144
coeffs: [u8; PDM_NUM_COEFFS * mem::size_of::<u32>()],
145-
unk3: u32,
146-
mic_turn_on_time_ms: u32,
147-
_zero0: u64,
148-
_zero1: u64,
149-
unk4: u32,
150-
mic_settle_time_ms: u32,
145+
unk3: U32,
146+
mic_turn_on_time_ms: U32,
147+
_zero0: [u8; 8],
148+
_zero1: [u8; 8],
149+
unk4: U32,
150+
mic_settle_time_ms: U32,
151151
_zero2: [u8; 69], // ?????
152+
_pad_extra: u8, // extra padding to increase the struct size to multiple of mem::size_of::<u32>()
152153
}
154+
// PDMConfig is intended to use `#[repr(C, packed)]` but this
155+
// conflicts ith pin_init. Instead just ensure that it has the same size as if
156+
// it where packed.
157+
static_assert!(mem::size_of::<PDMConfig>() == 36 + 14 + (120 * 4) + 32 + 69 + 1);
153158

154159
unsafe impl Zeroable for PDMConfig {}
155160

156-
#[repr(C, packed)]
161+
#[repr(C, packed(4))]
157162
#[derive(Debug, Copy, Clone)]
158163
struct DecimatorConfig {
159164
latency: u32,
@@ -165,16 +170,20 @@ struct DecimatorConfig {
165170
coeff_bulk: u32,
166171
coeffs: [u8; PDM_NUM_COEFFS * mem::size_of::<u32>()],
167172
}
173+
// DecimatorConfig is intended to use `#[repr(C, packed)]` but this
174+
// conflicts ith pin_init. Instead just ensure that it has the same size as if
175+
// it where packed.
176+
static_assert!(mem::size_of::<DecimatorConfig>() == 16 + (120 * 4));
168177

169178
unsafe impl Zeroable for DecimatorConfig {}
170179

171-
#[repr(C, packed)]
180+
#[repr(C, packed(4))]
172181
#[derive(Clone, Copy, Default, Debug)]
173182
struct PowerSetting {
174183
dev_id: u32,
175184
cookie: u32,
176185
_unk0: u32,
177-
_zero0: u64,
186+
_zero0: [u8; 8],
178187
target_pstate: u32,
179188
unk1: u32,
180189
_zero1: [u8; 20],
@@ -192,21 +201,29 @@ impl PowerSetting {
192201
}
193202
}
194203

195-
#[repr(C, packed)]
204+
#[repr(C)]
196205
#[derive(Clone, Copy, Default, Debug)]
197206
struct AudioSetDeviceProp<T> {
198207
_zero0: u32,
199208
unk0: u32,
200209
calltype: u32,
201-
_zero1: u64,
202-
_zero2: u64,
210+
_zero1: [u8; 8],
211+
_zero2: [u8; 8],
203212
_pad0: u32,
204-
len: u64,
213+
len: u32,
214+
_pad1: u32,
205215
dev_id: u32,
206216
modifier: u32,
207217
len2: u32,
208218
data: T,
209219
}
220+
// AudioSetDeviceProp<T> is intended to use `#[repr(C, packed)]` but this
221+
// conflicts ith pin_init. Instead just ensure that it has the same size as if
222+
// it where packed.
223+
static_assert!(mem::size_of::<AudioSetDeviceProp<PDMConfig>>() == 52 + mem::size_of::<PDMConfig>());
224+
static_assert!(mem::size_of::<AudioSetDeviceProp<DecimatorConfig>>() == 52 + mem::size_of::<DecimatorConfig>());
225+
static_assert!(mem::size_of::<AudioSetDeviceProp<LpaiChannelConfig>>() == 52 + mem::size_of::<LpaiChannelConfig>());
226+
static_assert!(mem::size_of::<AudioSetDeviceProp<PowerSetting>>() == 52 + mem::size_of::<PowerSetting>());
210227

211228
impl<T: Default> AudioSetDeviceProp<T> {
212229
fn new(dev_id: u32, modifier: u32, data: T) -> AudioSetDeviceProp<T> {
@@ -215,7 +232,7 @@ impl<T: Default> AudioSetDeviceProp<T> {
215232
calltype: CALLTYPE_AUDIO_SET_PROP,
216233
dev_id,
217234
modifier,
218-
len: mem::size_of::<T>() as u64 + 0x30,
235+
len: mem::size_of::<T>() as u32 + 0x30,
219236
len2: mem::size_of::<T>() as u32,
220237
data,
221238
..AudioSetDeviceProp::default()
@@ -240,7 +257,7 @@ impl<T: Zeroable> AudioSetDeviceProp<T> {
240257
calltype: CALLTYPE_AUDIO_SET_PROP,
241258
dev_id,
242259
modifier,
243-
len: mem::size_of::<T>() as u64 + 0x30,
260+
len: mem::size_of::<T>() as u32 + 0x30,
244261
len2: mem::size_of::<T>() as u32,
245262
data <- data,
246263
..Zeroable::init_zeroed()
@@ -290,13 +307,13 @@ impl SndSocAopData {
290307
ratio1: DECIMATION_RATIOS[0],
291308
ratio2: DECIMATION_RATIOS[1],
292309
ratio3: DECIMATION_RATIOS[2],
293-
filter_lengths: FILTER_LENGTHS,
294-
coeff_bulk: PDM_NUM_COEFFS as u32,
310+
filter_lengths: U32(FILTER_LENGTHS),
311+
coeff_bulk: U32(PDM_NUM_COEFFS as u32),
295312
coeffs: COEFFICIENTS,
296-
unk3: 1,
297-
mic_turn_on_time_ms: 20,
298-
unk4: 1,
299-
mic_settle_time_ms: 50,
313+
unk3: U32(1),
314+
mic_turn_on_time_ms: U32(20),
315+
unk4: U32(1),
316+
mic_settle_time_ms: U32(50),
300317
..Zeroable::init_zeroed()
301318
});
302319
let set_prop = AudioSetDeviceProp::<PDMConfig>::try_init(AUDIO_DEV_PDM0, 200, pdm_cfg);

0 commit comments

Comments
 (0)