Skip to content

Commit cce3858

Browse files
committed
Fix unsound lifetime on LinuxI2CMessage
The type alias to a struct without a lifetime parameter of its own does not actually enforce that the borrowed buffer is still valid at the time it is passed to the ioctl.
1 parent f832946 commit cce3858

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).
1212
- Updated nix to version `0.25`.
1313
- Updated nix to version `0.24`; only use the `ioctl` feature.
1414
- Use `File.read_exact` instead of `File.read` in `LinuxI2CDevice.read` so that the buffer is filled.
15+
- Fix the lifetime parameter on LinuxI2CMessage to ensure that it does not outlive the buffer it points to.
1516

1617
## [v0.5.1] - 2021-11-22
1718

src/ffi.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
1313
use nix;
1414
use std::io::Cursor;
15+
use std::marker::PhantomData;
1516
use std::mem;
1617
use std::os::unix::prelude::*;
1718
use std::ptr;
1819

1920
pub type I2CError = nix::Error;
2021

2122
#[repr(C)]
22-
pub struct i2c_msg {
23+
pub struct i2c_msg<'a> {
2324
/// slave address
2425
pub(crate) addr: u16,
2526
/// serialized I2CMsgFlags
@@ -28,6 +29,8 @@ pub struct i2c_msg {
2829
pub(crate) len: u16,
2930
/// pointer to msg data
3031
pub(crate) buf: *const u8,
32+
33+
pub(crate) _p: PhantomData<&'a mut [u8]>,
3134
}
3235

3336
bitflags! {
@@ -143,9 +146,9 @@ pub struct i2c_smbus_ioctl_data {
143146
/// This is the structure as used in the I2C_RDWR ioctl call
144147
// see linux/i2c-dev.h
145148
#[repr(C)]
146-
pub struct i2c_rdwr_ioctl_data {
149+
pub struct i2c_rdwr_ioctl_data<'a> {
147150
// struct i2c_msg __user *msgs;
148-
msgs: *mut i2c_msg,
151+
msgs: *mut i2c_msg<'a>,
149152
// __u32 nmsgs;
150153
nmsgs: u32,
151154
}

src/linux.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::fs::File;
1515
use std::fs::OpenOptions;
1616
use std::io;
1717
use std::io::prelude::*;
18+
use std::marker::PhantomData;
1819
use std::os::unix::prelude::*;
1920
use std::path::Path;
2021

@@ -316,7 +317,7 @@ impl LinuxI2CBus {
316317
}
317318

318319
/// Linux I2C message
319-
pub type LinuxI2CMessage<'a> = ffi::i2c_msg;
320+
pub type LinuxI2CMessage<'a> = ffi::i2c_msg<'a>;
320321

321322
impl<'a> I2CTransfer<'a> for LinuxI2CBus {
322323
type Error = LinuxI2CError;
@@ -354,21 +355,23 @@ bitflags! {
354355
}
355356

356357
impl<'a> I2CMessage<'a> for LinuxI2CMessage<'a> {
357-
fn read(data: &'a mut [u8]) -> LinuxI2CMessage {
358+
fn read(data: &'a mut [u8]) -> LinuxI2CMessage<'a> {
358359
Self {
359360
addr: 0, // will be filled later
360361
flags: I2CMessageFlags::READ.bits(),
361362
len: data.len() as u16,
362363
buf: data.as_ptr(),
364+
_p: PhantomData,
363365
}
364366
}
365367

366-
fn write(data: &'a [u8]) -> LinuxI2CMessage {
368+
fn write(data: &'a [u8]) -> LinuxI2CMessage<'a> {
367369
Self {
368370
addr: 0, // will be filled later
369371
flags: I2CMessageFlags::empty().bits(),
370372
len: data.len() as u16,
371373
buf: data.as_ptr(),
374+
_p: PhantomData,
372375
}
373376
}
374377
}
@@ -381,6 +384,7 @@ impl<'a> LinuxI2CMessage<'a> {
381384
flags: self.flags,
382385
len: self.len,
383386
buf: self.buf,
387+
_p: PhantomData,
384388
}
385389
}
386390

@@ -391,6 +395,7 @@ impl<'a> LinuxI2CMessage<'a> {
391395
flags: flags.bits(),
392396
len: self.len,
393397
buf: self.buf,
398+
_p: PhantomData,
394399
}
395400
}
396401
}

0 commit comments

Comments
 (0)