@@ -198,7 +198,11 @@ fn raw_sendmsg<D: IntoIovec>(fd: RawFd, out_data: &[D], out_fds: &[RawFd]) -> Re
198
198
}
199
199
}
200
200
201
- fn raw_recvmsg ( fd : RawFd , iovecs : & mut [ iovec ] , in_fds : & mut [ RawFd ] ) -> Result < ( usize , usize ) > {
201
+ unsafe fn raw_recvmsg (
202
+ fd : RawFd ,
203
+ iovecs : & mut [ iovec ] ,
204
+ in_fds : & mut [ RawFd ] ,
205
+ ) -> Result < ( usize , usize ) > {
202
206
let cmsg_capacity = CMSG_SPACE ! ( size_of:: <RawFd >( ) * in_fds. len( ) ) ;
203
207
let mut cmsg_buffer = CmsgBuffer :: with_capacity ( cmsg_capacity) ;
204
208
let mut msg = new_msghdr ( iovecs) ;
@@ -212,7 +216,7 @@ fn raw_recvmsg(fd: RawFd, iovecs: &mut [iovec], in_fds: &mut [RawFd]) -> Result<
212
216
// Safe because the msghdr was properly constructed from valid (or null) pointers of the
213
217
// indicated length and we check the return value.
214
218
// TODO: Should we handle MSG_TRUNC in a specific way?
215
- let total_read = unsafe { recvmsg ( fd, & mut msg, 0 ) } ;
219
+ let total_read = recvmsg ( fd, & mut msg, 0 ) ;
216
220
if total_read == -1 {
217
221
return Err ( Error :: last ( ) ) ;
218
222
}
@@ -233,7 +237,7 @@ fn raw_recvmsg(fd: RawFd, iovecs: &mut [iovec], in_fds: &mut [RawFd]) -> Result<
233
237
// Safe because we checked that cmsg_ptr was non-null, and the loop is constructed such
234
238
// that it only happens when there is at least sizeof(cmsghdr) space after the pointer to
235
239
// read.
236
- let cmsg = unsafe { ( cmsg_ptr as * mut cmsghdr ) . read_unaligned ( ) } ;
240
+ let cmsg = ( cmsg_ptr as * mut cmsghdr ) . read_unaligned ( ) ;
237
241
if cmsg. cmsg_level == SOL_SOCKET && cmsg. cmsg_type == SCM_RIGHTS {
238
242
let fds_count = ( ( cmsg. cmsg_len - CMSG_LEN ! ( 0 ) ) as usize ) / size_of :: < RawFd > ( ) ;
239
243
// The sender can transmit more data than we can buffer. If a message is too long to
@@ -250,22 +254,18 @@ fn raw_recvmsg(fd: RawFd, iovecs: &mut [iovec], in_fds: &mut [RawFd]) -> Result<
250
254
let raw_fds_ptr = CMSG_DATA ( cmsg_ptr) ;
251
255
// The cmsg_ptr is valid here because is checked at the beginning of the
252
256
// loop and it is assured to have `fds_count` fds available.
253
- unsafe {
254
- let raw_fd = * ( raw_fds_ptr. wrapping_add ( fd_offset) ) as c_int ;
255
- libc:: close ( raw_fd)
256
- } ;
257
+ let raw_fd = * ( raw_fds_ptr. wrapping_add ( fd_offset) ) as c_int ;
258
+ libc:: close ( raw_fd) ;
257
259
}
258
260
} else {
259
261
// Safe because `cmsg_ptr` is checked against null and we copy from `cmesg_buffer` to
260
262
// `in_fds` according to their current capacity.
261
- unsafe {
262
- copy_nonoverlapping (
263
- CMSG_DATA ( cmsg_ptr) ,
264
- in_fds[ copied_fds_count..( copied_fds_count + fds_to_be_copied_count) ]
265
- . as_mut_ptr ( ) ,
266
- fds_to_be_copied_count,
267
- ) ;
268
- }
263
+ copy_nonoverlapping (
264
+ CMSG_DATA ( cmsg_ptr) ,
265
+ in_fds[ copied_fds_count..( copied_fds_count + fds_to_be_copied_count) ]
266
+ . as_mut_ptr ( ) ,
267
+ fds_to_be_copied_count,
268
+ ) ;
269
269
270
270
copied_fds_count += fds_to_be_copied_count;
271
271
}
@@ -276,7 +276,7 @@ fn raw_recvmsg(fd: RawFd, iovecs: &mut [iovec], in_fds: &mut [RawFd]) -> Result<
276
276
for fd in in_fds. iter ( ) . take ( copied_fds_count) {
277
277
// This is safe because we close only the previously copied fds. We do not care
278
278
// about `close` return code.
279
- unsafe { libc:: close ( * fd) } ;
279
+ libc:: close ( * fd) ;
280
280
}
281
281
282
282
return Err ( Error :: new ( libc:: ENOBUFS ) ) ;
@@ -319,9 +319,10 @@ fn raw_recvmsg(fd: RawFd, iovecs: &mut [iovec], in_fds: &mut [RawFd]) -> Result<
319
319
/// iov_base: buf.as_mut_ptr() as *mut c_void,
320
320
/// iov_len: buf.len(),
321
321
/// }];
322
- /// let (read_count, file_count) = s2
323
- /// .recv_with_fds(&mut iovecs[..], &mut files)
324
- /// .expect("failed to recv fd");
322
+ /// let (read_count, file_count) = unsafe {
323
+ /// s2.recv_with_fds(&mut iovecs[..], &mut files)
324
+ /// .expect("failed to recv fd")
325
+ /// };
325
326
///
326
327
/// let mut file = unsafe { File::from_raw_fd(files[0]) };
327
328
/// file.write(unsafe { from_raw_parts(&1203u64 as *const u64 as *const u8, 8) })
@@ -370,7 +371,9 @@ pub trait ScmSocket {
370
371
iov_len : buf. len ( ) ,
371
372
} ] ;
372
373
373
- let ( read_count, fd_count) = self . recv_with_fds ( & mut iovecs[ ..] , & mut fd) ?;
374
+ // Safe because we have mutably borrowed buf and it's safe to write arbitrary data
375
+ // to a slice.
376
+ let ( read_count, fd_count) = unsafe { self . recv_with_fds ( & mut iovecs[ ..] , & mut fd) ? } ;
374
377
let file = if fd_count == 0 {
375
378
None
376
379
} else {
@@ -394,7 +397,16 @@ pub trait ScmSocket {
394
397
/// returned tuple. The caller owns these file descriptors, but they will not be
395
398
/// closed on drop like a `File`-like type would be. It is recommended that each valid
396
399
/// file descriptor gets wrapped in a drop type that closes it after this returns.
397
- fn recv_with_fds ( & self , iovecs : & mut [ iovec ] , fds : & mut [ RawFd ] ) -> Result < ( usize , usize ) > {
400
+ ///
401
+ /// # Safety
402
+ ///
403
+ /// It is the callers responsibility to ensure it is safe for arbitrary data to be
404
+ /// written to the iovec pointers.
405
+ unsafe fn recv_with_fds (
406
+ & self ,
407
+ iovecs : & mut [ iovec ] ,
408
+ fds : & mut [ RawFd ] ,
409
+ ) -> Result < ( usize , usize ) > {
398
410
raw_recvmsg ( self . socket_fd ( ) , iovecs, fds)
399
411
}
400
412
}
@@ -503,9 +515,10 @@ mod tests {
503
515
iov_base : buf. as_mut_ptr ( ) as * mut c_void ,
504
516
iov_len : buf. len ( ) ,
505
517
} ] ;
506
- let ( read_count, file_count) = s2
507
- . recv_with_fds ( & mut iovecs[ ..] , & mut files)
508
- . expect ( "failed to recv data" ) ;
518
+ let ( read_count, file_count) = unsafe {
519
+ s2. recv_with_fds ( & mut iovecs[ ..] , & mut files)
520
+ . expect ( "failed to recv data" )
521
+ } ;
509
522
510
523
assert_eq ! ( read_count, 6 ) ;
511
524
assert_eq ! ( file_count, 0 ) ;
@@ -556,9 +569,10 @@ mod tests {
556
569
iov_base : buf. as_mut_ptr ( ) as * mut c_void ,
557
570
iov_len : buf. len ( ) ,
558
571
} ] ;
559
- let ( read_count, file_count) = s2
560
- . recv_with_fds ( & mut iovecs[ ..] , & mut files)
561
- . expect ( "failed to recv fd" ) ;
572
+ let ( read_count, file_count) = unsafe {
573
+ s2. recv_with_fds ( & mut iovecs[ ..] , & mut files)
574
+ . expect ( "failed to recv fd" )
575
+ } ;
562
576
563
577
assert_eq ! ( read_count, 1 ) ;
564
578
assert_eq ! ( buf[ 0 ] , 237 ) ;
@@ -606,7 +620,7 @@ mod tests {
606
620
iov_base : buf. as_mut_ptr ( ) as * mut c_void ,
607
621
iov_len : buf. len ( ) ,
608
622
} ] ;
609
- assert ! ( s2. recv_with_fds( & mut iovecs[ ..] , & mut files) . is_err( ) ) ;
623
+ assert ! ( unsafe { s2. recv_with_fds( & mut iovecs[ ..] , & mut files) . is_err( ) } ) ;
610
624
}
611
625
612
626
// Exercise the code paths that activate the issue of receiving part of the sent ancillary
@@ -639,6 +653,6 @@ mod tests {
639
653
iov_base : buf. as_mut_ptr ( ) as * mut c_void ,
640
654
iov_len : buf. len ( ) ,
641
655
} ] ;
642
- assert ! ( s2. recv_with_fds( & mut iovecs[ ..] , & mut files) . is_err( ) ) ;
656
+ assert ! ( unsafe { s2. recv_with_fds( & mut iovecs[ ..] , & mut files) . is_err( ) } ) ;
643
657
}
644
658
}
0 commit comments