1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Implementation of the AIDL interface of Vmnic.
16 
17 use anyhow::{anyhow, Context, Result};
18 use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::IVmnic::IVmnic;
19 use binder::{self, Interface, IntoBinderResult, ParcelFileDescriptor};
20 use libc::{c_char, c_int, c_short, ifreq, IFF_NO_PI, IFF_TAP, IFF_UP, IFF_VNET_HDR, IFNAMSIZ};
21 use log::info;
22 use nix::{ioctl_write_int_bad, ioctl_write_ptr_bad};
23 use nix::sys::ioctl::ioctl_num_type;
24 use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
25 use std::ffi::{CStr, CString};
26 use std::fs::File;
27 use std::os::fd::{AsRawFd, RawFd};
28 use std::slice::from_raw_parts;
29 
30 const TUNGETIFF: ioctl_num_type = 0x800454d2u32 as c_int;
31 const TUNSETIFF: ioctl_num_type = 0x400454ca;
32 const TUNSETPERSIST: ioctl_num_type = 0x400454cb;
33 const SIOCSIFFLAGS: ioctl_num_type = 0x00008914;
34 
35 ioctl_write_ptr_bad!(ioctl_tungetiff, TUNGETIFF, ifreq);
36 ioctl_write_ptr_bad!(ioctl_tunsetiff, TUNSETIFF, ifreq);
37 ioctl_write_int_bad!(ioctl_tunsetpersist, TUNSETPERSIST);
38 ioctl_write_ptr_bad!(ioctl_siocsifflags, SIOCSIFFLAGS, ifreq);
39 
validate_ifname(ifname: &[c_char]) -> Result<()>40 fn validate_ifname(ifname: &[c_char]) -> Result<()> {
41     if ifname.len() >= IFNAMSIZ {
42         return Err(anyhow!(format!("Interface name is too long")));
43     }
44     Ok(())
45 }
46 
create_tap_interface(fd: RawFd, sockfd: c_int, ifname: &[c_char]) -> Result<()>47 fn create_tap_interface(fd: RawFd, sockfd: c_int, ifname: &[c_char]) -> Result<()> {
48     // SAFETY: All-zero is a valid value for the ifreq type.
49     let mut ifr: ifreq = unsafe { std::mem::zeroed() };
50     ifr.ifr_ifru.ifru_flags = (IFF_TAP | IFF_NO_PI | IFF_VNET_HDR) as c_short;
51     ifr.ifr_name[..ifname.len()].copy_from_slice(ifname);
52     // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
53     unsafe { ioctl_tunsetiff(fd, &ifr) }.context("Failed to ioctl TUNSETIFF")?;
54     // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
55     unsafe { ioctl_tunsetpersist(fd, 1) }.context("Failed to ioctl TUNSETPERSIST")?;
56     // SAFETY: ifr_ifru holds ifru_flags in its union field.
57     unsafe { ifr.ifr_ifru.ifru_flags |= IFF_UP as c_short };
58     // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
59     unsafe { ioctl_siocsifflags(sockfd, &ifr) }.context("Failed to ioctl SIOCSIFFLAGS")?;
60     Ok(())
61 }
62 
get_tap_ifreq(fd: RawFd) -> Result<ifreq>63 fn get_tap_ifreq(fd: RawFd) -> Result<ifreq> {
64     // SAFETY: All-zero is a valid value for the ifreq type.
65     let ifr: ifreq = unsafe { std::mem::zeroed() };
66     // SAFETY: Returned `ifr` of given file descriptor is set from TUNSETIFF ioctl while executing
67     // create_tap_interface(fd, sockfd, ifname). So the variable `ifr` should be safe.
68     unsafe { ioctl_tungetiff(fd, &ifr) }.context("Failed to ioctl TUNGETIFF")?;
69     Ok(ifr)
70 }
71 
delete_tap_interface(fd: RawFd, sockfd: c_int, ifr: &mut ifreq) -> Result<()>72 fn delete_tap_interface(fd: RawFd, sockfd: c_int, ifr: &mut ifreq) -> Result<()> {
73     // SAFETY: After calling TUNGETIFF, ifr_ifru holds ifru_flags in its union field.
74     unsafe { ifr.ifr_ifru.ifru_flags &= !IFF_UP as c_short };
75     // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
76     unsafe { ioctl_siocsifflags(sockfd, ifr) }.context("Failed to ioctl SIOCSIFFLAGS")?;
77     // SAFETY: It modifies the state in the kernel, not the state of this process in any way.
78     unsafe { ioctl_tunsetpersist(fd, 0) }.context("Failed to ioctl TUNSETPERSIST")?;
79     Ok(())
80 }
81 
82 #[derive(Debug, Default)]
83 pub struct Vmnic {}
84 
85 impl Vmnic {
init() -> Vmnic86     pub fn init() -> Vmnic {
87         Vmnic::default()
88     }
89 }
90 
91 impl Interface for Vmnic {}
92 
93 impl IVmnic for Vmnic {
createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor>94     fn createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
95         let ifname = CString::new(format!("avf_tap_{iface_name_suffix}"))
96             .context(format!(
97                 "Failed to construct TAP interface name as CString: avf_tap_{iface_name_suffix}"
98             ))
99             .or_service_specific_exception(-1)?;
100         let ifname_bytes = ifname.as_bytes_with_nul();
101         // SAFETY: Converting from &[u8] into &[c_char].
102         let ifname_bytes =
103             unsafe { from_raw_parts(ifname_bytes.as_ptr().cast::<c_char>(), ifname_bytes.len()) };
104         validate_ifname(ifname_bytes)
105             .context(format!("Invalid interface name: {ifname:#?}"))
106             .or_service_specific_exception(-1)?;
107 
108         let tunfd = File::open("/dev/tun")
109             .context("Failed to open /dev/tun")
110             .or_service_specific_exception(-1)?;
111         let sock = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None)
112             .context("Failed to create socket")
113             .or_service_specific_exception(-1)?;
114         create_tap_interface(tunfd.as_raw_fd(), sock.as_raw_fd(), ifname_bytes)
115             .context(format!("Failed to create TAP interface: {ifname:#?}"))
116             .or_service_specific_exception(-1)?;
117 
118         info!("Created TAP network interface: {ifname:#?}");
119         Ok(ParcelFileDescriptor::new(tunfd))
120     }
121 
deleteTapInterface(&self, tapfd: &ParcelFileDescriptor) -> binder::Result<()>122     fn deleteTapInterface(&self, tapfd: &ParcelFileDescriptor) -> binder::Result<()> {
123         let tap = tapfd.as_raw_fd();
124         let mut tap_ifreq = get_tap_ifreq(tap)
125             .context("Failed to get ifreq of TAP interface")
126             .or_service_specific_exception(-1)?;
127         // SAFETY: tap_ifreq.ifr_name is null-terminated within IFNAMSIZ, validated when creating
128         // TAP interface.
129         let ifname = unsafe { CStr::from_ptr(tap_ifreq.ifr_name.as_ptr()) };
130 
131         let sock = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None)
132             .context("Failed to create socket")
133             .or_service_specific_exception(-1)?;
134         delete_tap_interface(tap, sock.as_raw_fd(), &mut tap_ifreq)
135             .context(format!("Failed to create TAP interface: {ifname:#?}"))
136             .or_service_specific_exception(-1)?;
137 
138         info!("Deleted TAP network interface: {ifname:#?}");
139         Ok(())
140     }
141 }
142