1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 use log::error; 18 use nix::sys::stat::{mode_t, Mode, SFlag}; 19 use std::io; 20 21 use super::VirtFdService; 22 23 /// Default/assumed mode of files not created by authfs. 24 /// 25 /// For files that are given to authfs as FDs (i.e. not created through authfs), their mode is 26 /// unknown (or untrusted) until it is ever set. The default mode is just to make it 27 /// readable/writable to VFS. When the mode is set, the value on fd_server is supposed to become 28 /// consistent. 29 const DEFAULT_FILE_MODE: Mode = 30 Mode::from_bits_truncate(Mode::S_IRUSR.bits() | Mode::S_IWUSR.bits()); 31 32 /// Default/assumed mode of directories not created by authfs. 33 /// 34 /// See above. 35 const DEFAULT_DIR_MODE: Mode = Mode::S_IRWXU; 36 37 /// `Attr` maintains the local truth for attributes (e.g. mode and type) while allowing setting the 38 /// remote attribute for the file description. 39 pub struct Attr { 40 service: VirtFdService, 41 mode: Mode, 42 remote_fd: i32, 43 is_dir: bool, 44 } 45 46 impl Attr { new_file(service: VirtFdService, remote_fd: i32) -> Attr47 pub fn new_file(service: VirtFdService, remote_fd: i32) -> Attr { 48 Attr { service, mode: DEFAULT_FILE_MODE, remote_fd, is_dir: false } 49 } 50 new_dir(service: VirtFdService, remote_fd: i32) -> Attr51 pub fn new_dir(service: VirtFdService, remote_fd: i32) -> Attr { 52 Attr { service, mode: DEFAULT_DIR_MODE, remote_fd, is_dir: true } 53 } 54 new_file_with_mode(service: VirtFdService, remote_fd: i32, mode: mode_t) -> Attr55 pub fn new_file_with_mode(service: VirtFdService, remote_fd: i32, mode: mode_t) -> Attr { 56 Attr { service, mode: Mode::from_bits_truncate(mode), remote_fd, is_dir: false } 57 } 58 new_dir_with_mode(service: VirtFdService, remote_fd: i32, mode: mode_t) -> Attr59 pub fn new_dir_with_mode(service: VirtFdService, remote_fd: i32, mode: mode_t) -> Attr { 60 Attr { service, mode: Mode::from_bits_truncate(mode), remote_fd, is_dir: true } 61 } 62 mode(&self) -> u3263 pub fn mode(&self) -> u32 { 64 self.mode.bits() 65 } 66 67 /// Sets the file mode. 68 /// 69 /// In addition to the actual file mode, `encoded_mode` also contains information of the file 70 /// type. set_mode(&mut self, encoded_mode: u32) -> io::Result<()>71 pub fn set_mode(&mut self, encoded_mode: u32) -> io::Result<()> { 72 let new_sflag = SFlag::from_bits_truncate(encoded_mode); 73 let new_mode = Mode::from_bits_truncate(encoded_mode); 74 75 let type_flag = if self.is_dir { SFlag::S_IFDIR } else { SFlag::S_IFREG }; 76 if !type_flag.contains(new_sflag) { 77 return Err(io::Error::from_raw_os_error(libc::EINVAL)); 78 } 79 80 // Request for update only if changing. 81 if new_mode != self.mode { 82 self.service.chmod(self.remote_fd, new_mode.bits() as i32).map_err(|e| { 83 error!( 84 "Failed to chmod (fd: {}, mode: {:o}) on fd_server: {:?}", 85 self.remote_fd, new_mode, e 86 ); 87 io::Error::from_raw_os_error(libc::EIO) 88 })?; 89 self.mode = new_mode; 90 } 91 Ok(()) 92 } 93 } 94