| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | // Copyright (C) 2024 Google LLC. |
| 4 | |
| 5 | //! Files and file descriptors. |
| 6 | //! |
| 7 | //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and |
| 8 | //! [`include/linux/file.h`](srctree/include/linux/file.h) |
| 9 | |
| 10 | use crate:: |
| 11 | bindings, |
| 12 | Credential, |
| 13 | , |
| 14 | fmt, |
| 15 | , |
| 16 | , |
| 17 | ; |
| 18 | use ptr; |
| 19 | |
| 20 | /// Primitive type representing the offset within a [`File`]. |
| 21 | /// |
| 22 | /// Type alias for `bindings::loff_t`. |
| 23 | pub type Offset = loff_t; |
| 24 | |
| 25 | /// Flags associated with a [`File`]. |
| 26 | |
| 27 | /// File is opened in append mode. |
| 28 | pub const O_APPEND: u32 = O_APPEND; |
| 29 | |
| 30 | /// Signal-driven I/O is enabled. |
| 31 | pub const O_ASYNC: u32 = FASYNC; |
| 32 | |
| 33 | /// Close-on-exec flag is set. |
| 34 | pub const O_CLOEXEC: u32 = O_CLOEXEC; |
| 35 | |
| 36 | /// File was created if it didn't already exist. |
| 37 | pub const O_CREAT: u32 = O_CREAT; |
| 38 | |
| 39 | /// Direct I/O is enabled for this file. |
| 40 | pub const O_DIRECT: u32 = O_DIRECT; |
| 41 | |
| 42 | /// File must be a directory. |
| 43 | pub const O_DIRECTORY: u32 = O_DIRECTORY; |
| 44 | |
| 45 | /// Like [`O_SYNC`] except metadata is not synced. |
| 46 | pub const O_DSYNC: u32 = O_DSYNC; |
| 47 | |
| 48 | /// Ensure that this file is created with the `open(2)` call. |
| 49 | pub const O_EXCL: u32 = O_EXCL; |
| 50 | |
| 51 | /// Large file size enabled (`off64_t` over `off_t`). |
| 52 | pub const O_LARGEFILE: u32 = O_LARGEFILE; |
| 53 | |
| 54 | /// Do not update the file last access time. |
| 55 | pub const O_NOATIME: u32 = O_NOATIME; |
| 56 | |
| 57 | /// File should not be used as process's controlling terminal. |
| 58 | pub const O_NOCTTY: u32 = O_NOCTTY; |
| 59 | |
| 60 | /// If basename of path is a symbolic link, fail open. |
| 61 | pub const O_NOFOLLOW: u32 = O_NOFOLLOW; |
| 62 | |
| 63 | /// File is using nonblocking I/O. |
| 64 | pub const O_NONBLOCK: u32 = O_NONBLOCK; |
| 65 | |
| 66 | /// File is using nonblocking I/O. |
| 67 | /// |
| 68 | /// This is effectively the same flag as [`O_NONBLOCK`] on all architectures |
| 69 | /// except SPARC64. |
| 70 | pub const O_NDELAY: u32 = O_NDELAY; |
| 71 | |
| 72 | /// Used to obtain a path file descriptor. |
| 73 | pub const O_PATH: u32 = O_PATH; |
| 74 | |
| 75 | /// Write operations on this file will flush data and metadata. |
| 76 | pub const O_SYNC: u32 = O_SYNC; |
| 77 | |
| 78 | /// This file is an unnamed temporary regular file. |
| 79 | pub const O_TMPFILE: u32 = O_TMPFILE; |
| 80 | |
| 81 | /// File should be truncated to length 0. |
| 82 | pub const O_TRUNC: u32 = O_TRUNC; |
| 83 | |
| 84 | /// Bitmask for access mode flags. |
| 85 | /// |
| 86 | /// # Examples |
| 87 | /// |
| 88 | /// ``` |
| 89 | /// use kernel::fs::file; |
| 90 | /// # fn do_something() {} |
| 91 | /// # let flags = 0; |
| 92 | /// if (flags & file::flags::O_ACCMODE) == file::flags::O_RDONLY { |
| 93 | /// do_something(); |
| 94 | /// } |
| 95 | /// ``` |
| 96 | pub const O_ACCMODE: u32 = O_ACCMODE; |
| 97 | |
| 98 | /// File is read only. |
| 99 | pub const O_RDONLY: u32 = O_RDONLY; |
| 100 | |
| 101 | /// File is write only. |
| 102 | pub const O_WRONLY: u32 = O_WRONLY; |
| 103 | |
| 104 | /// File can be both read and written. |
| 105 | pub const O_RDWR: u32 = O_RDWR; |
| 106 | |
| 107 | |
| 108 | /// Wraps the kernel's `struct file`. Thread safe. |
| 109 | /// |
| 110 | /// This represents an open file rather than a file on a filesystem. Processes generally reference |
| 111 | /// open files using file descriptors. However, file descriptors are not the same as files. A file |
| 112 | /// descriptor is just an integer that corresponds to a file, and a single file may be referenced |
| 113 | /// by multiple file descriptors. |
| 114 | /// |
| 115 | /// # Refcounting |
| 116 | /// |
| 117 | /// Instances of this type are reference-counted. The reference count is incremented by the |
| 118 | /// `fget`/`get_file` functions and decremented by `fput`. The Rust type `ARef<File>` represents a |
| 119 | /// pointer that owns a reference count on the file. |
| 120 | /// |
| 121 | /// Whenever a process opens a file descriptor (fd), it stores a pointer to the file in its fd |
| 122 | /// table (`struct files_struct`). This pointer owns a reference count to the file, ensuring the |
| 123 | /// file isn't prematurely deleted while the file descriptor is open. In Rust terminology, the |
| 124 | /// pointers in `struct files_struct` are `ARef<File>` pointers. |
| 125 | /// |
| 126 | /// ## Light refcounts |
| 127 | /// |
| 128 | /// Whenever a process has an fd to a file, it may use something called a "light refcount" as a |
| 129 | /// performance optimization. Light refcounts are acquired by calling `fdget` and released with |
| 130 | /// `fdput`. The idea behind light refcounts is that if the fd is not closed between the calls to |
| 131 | /// `fdget` and `fdput`, then the refcount cannot hit zero during that time, as the `struct |
| 132 | /// files_struct` holds a reference until the fd is closed. This means that it's safe to access the |
| 133 | /// file even if `fdget` does not increment the refcount. |
| 134 | /// |
| 135 | /// The requirement that the fd is not closed during a light refcount applies globally across all |
| 136 | /// threads - not just on the thread using the light refcount. For this reason, light refcounts are |
| 137 | /// only used when the `struct files_struct` is not shared with other threads, since this ensures |
| 138 | /// that other unrelated threads cannot suddenly start using the fd and close it. Therefore, |
| 139 | /// calling `fdget` on a shared `struct files_struct` creates a normal refcount instead of a light |
| 140 | /// refcount. |
| 141 | /// |
| 142 | /// Light reference counts must be released with `fdput` before the system call returns to |
| 143 | /// userspace. This means that if you wait until the current system call returns to userspace, then |
| 144 | /// all light refcounts that existed at the time have gone away. |
| 145 | /// |
| 146 | /// ### The file position |
| 147 | /// |
| 148 | /// Each `struct file` has a position integer, which is protected by the `f_pos_lock` mutex. |
| 149 | /// However, if the `struct file` is not shared, then the kernel may avoid taking the lock as a |
| 150 | /// performance optimization. |
| 151 | /// |
| 152 | /// The condition for avoiding the `f_pos_lock` mutex is different from the condition for using |
| 153 | /// `fdget`. With `fdget`, you may avoid incrementing the refcount as long as the current fd table |
| 154 | /// is not shared; it is okay if there are other fd tables that also reference the same `struct |
| 155 | /// file`. However, `fdget_pos` can only avoid taking the `f_pos_lock` if the entire `struct file` |
| 156 | /// is not shared, as different processes with an fd to the same `struct file` share the same |
| 157 | /// position. |
| 158 | /// |
| 159 | /// To represent files that are not thread safe due to this optimization, the [`LocalFile`] type is |
| 160 | /// used. |
| 161 | /// |
| 162 | /// ## Rust references |
| 163 | /// |
| 164 | /// The reference type `&File` is similar to light refcounts: |
| 165 | /// |
| 166 | /// * `&File` references don't own a reference count. They can only exist as long as the reference |
| 167 | /// count stays positive, and can only be created when there is some mechanism in place to ensure |
| 168 | /// this. |
| 169 | /// |
| 170 | /// * The Rust borrow-checker normally ensures this by enforcing that the `ARef<File>` from which |
| 171 | /// a `&File` is created outlives the `&File`. |
| 172 | /// |
| 173 | /// * Using the unsafe [`File::from_raw_file`] means that it is up to the caller to ensure that the |
| 174 | /// `&File` only exists while the reference count is positive. |
| 175 | /// |
| 176 | /// * You can think of `fdget` as using an fd to look up an `ARef<File>` in the `struct |
| 177 | /// files_struct` and create an `&File` from it. The "fd cannot be closed" rule is like the Rust |
| 178 | /// rule "the `ARef<File>` must outlive the `&File`". |
| 179 | /// |
| 180 | /// # Invariants |
| 181 | /// |
| 182 | /// * All instances of this type are refcounted using the `f_count` field. |
| 183 | /// * There must not be any active calls to `fdget_pos` on this file that did not take the |
| 184 | /// `f_pos_lock` mutex. |
| 185 | |
| 186 | |
| 187 | inner: , |
| 188 | |
| 189 | |
| 190 | // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the |
| 191 | // `f_pos_lock` mutex, so it is safe to transfer it between threads. |
| 192 | unsafe |
| 193 | |
| 194 | // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the |
| 195 | // `f_pos_lock` mutex, so it is safe to access its methods from several threads in parallel. |
| 196 | unsafe |
| 197 | |
| 198 | // SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation |
| 199 | // makes `ARef<File>` own a normal refcount. |
| 200 | unsafe |
| 201 | |
| 202 | |
| 203 | // SAFETY: The existence of a shared reference means that the refcount is nonzero. |
| 204 | unsafe ; |
| 205 | |
| 206 | |
| 207 | |
| 208 | unsafe |
| 209 | // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we |
| 210 | // may drop it. The cast is okay since `File` has the same representation as `struct file`. |
| 211 | unsafe |
| 212 | |
| 213 | |
| 214 | |
| 215 | /// Wraps the kernel's `struct file`. Not thread safe. |
| 216 | /// |
| 217 | /// This type represents a file that is not known to be safe to transfer across thread boundaries. |
| 218 | /// To obtain a thread-safe [`File`], use the [`assume_no_fdget_pos`] conversion. |
| 219 | /// |
| 220 | /// See the documentation for [`File`] for more information. |
| 221 | /// |
| 222 | /// # Invariants |
| 223 | /// |
| 224 | /// * All instances of this type are refcounted using the `f_count` field. |
| 225 | /// * If there is an active call to `fdget_pos` that did not take the `f_pos_lock` mutex, then it |
| 226 | /// must be on the same thread as this file. |
| 227 | /// |
| 228 | /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos |
| 229 | |
| 230 | |
| 231 | inner: , |
| 232 | |
| 233 | |
| 234 | // SAFETY: The type invariants guarantee that `LocalFile` is always ref-counted. This implementation |
| 235 | // makes `ARef<LocalFile>` own a normal refcount. |
| 236 | unsafe |
| 237 | |
| 238 | |
| 239 | // SAFETY: The existence of a shared reference means that the refcount is nonzero. |
| 240 | unsafe ; |
| 241 | |
| 242 | |
| 243 | |
| 244 | unsafe |
| 245 | // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we |
| 246 | // may drop it. The cast is okay since `LocalFile` has the same representation as |
| 247 | // `struct file`. |
| 248 | unsafe |
| 249 | |
| 250 | |
| 251 | |
| 252 | |
| 253 | /// Constructs a new `struct file` wrapper from a file descriptor. |
| 254 | /// |
| 255 | /// The file descriptor belongs to the current process, and there might be active local calls |
| 256 | /// to `fdget_pos` on the same file. |
| 257 | /// |
| 258 | /// To obtain an `ARef<File>`, use the [`assume_no_fdget_pos`] function to convert. |
| 259 | /// |
| 260 | /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos |
| 261 | |
| 262 | |
| 263 | // SAFETY: FFI call, there are no requirements on `fd`. |
| 264 | let ptr = new.ok_or?; |
| 265 | |
| 266 | // SAFETY: `bindings::fget` created a refcount, and we pass ownership of it to the `ARef`. |
| 267 | // |
| 268 | // INVARIANT: This file is in the fd table on this thread, so either all `fdget_pos` calls |
| 269 | // are on this thread, or the file is shared, in which case `fdget_pos` calls took the |
| 270 | // `f_pos_lock` mutex. |
| 271 | Ok |
| 272 | |
| 273 | |
| 274 | /// Creates a reference to a [`LocalFile`] from a valid pointer. |
| 275 | /// |
| 276 | /// # Safety |
| 277 | /// |
| 278 | /// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is |
| 279 | /// positive for the duration of `'a`. |
| 280 | /// * The caller must ensure that if there is an active call to `fdget_pos` that did not take |
| 281 | /// the `f_pos_lock` mutex, then that call is on the current thread. |
| 282 | |
| 283 | pub unsafe |
| 284 | // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the |
| 285 | // duration of `'a`. The cast is okay because `LocalFile` is `repr(transparent)`. |
| 286 | // |
| 287 | // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls. |
| 288 | unsafe |
| 289 | |
| 290 | |
| 291 | /// Assume that there are no active `fdget_pos` calls that prevent us from sharing this file. |
| 292 | /// |
| 293 | /// This makes it safe to transfer this file to other threads. No checks are performed, and |
| 294 | /// using it incorrectly may lead to a data race on the file position if the file is shared |
| 295 | /// with another thread. |
| 296 | /// |
| 297 | /// This method is intended to be used together with [`LocalFile::fget`] when the caller knows |
| 298 | /// statically that there are no `fdget_pos` calls on the current thread. For example, you |
| 299 | /// might use it when calling `fget` from an ioctl, since ioctls usually do not touch the file |
| 300 | /// position. |
| 301 | /// |
| 302 | /// # Safety |
| 303 | /// |
| 304 | /// There must not be any active `fdget_pos` calls on the current thread. |
| 305 | |
| 306 | pub unsafe |
| 307 | // INVARIANT: There are no `fdget_pos` calls on the current thread, and by the type |
| 308 | // invariants, if there is a `fdget_pos` call on another thread, then it took the |
| 309 | // `f_pos_lock` mutex. |
| 310 | // |
| 311 | // SAFETY: `LocalFile` and `File` have the same layout. |
| 312 | unsafe |
| 313 | |
| 314 | |
| 315 | /// Returns a raw pointer to the inner C struct. |
| 316 | |
| 317 | *mut file |
| 318 | self.inner.get |
| 319 | |
| 320 | |
| 321 | /// Returns the credentials of the task that originally opened the file. |
| 322 | |
| 323 | // SAFETY: It's okay to read the `f_cred` field without synchronization because `f_cred` is |
| 324 | // never changed after initialization of the file. |
| 325 | let ptr = unsafe ; |
| 326 | |
| 327 | // SAFETY: The signature of this function ensures that the caller will only access the |
| 328 | // returned credential while the file is still valid, and the C side ensures that the |
| 329 | // credential stays valid at least as long as the file. |
| 330 | unsafe |
| 331 | |
| 332 | |
| 333 | /// Returns the flags associated with the file. |
| 334 | /// |
| 335 | /// The flags are a combination of the constants in [`flags`]. |
| 336 | |
| 337 | |
| 338 | // This `read_volatile` is intended to correspond to a READ_ONCE call. |
| 339 | // |
| 340 | // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. |
| 341 | // |
| 342 | // FIXME(read_once): Replace with `read_once` when available on the Rust side. |
| 343 | unsafe |
| 344 | |
| 345 | |
| 346 | |
| 347 | |
| 348 | /// Creates a reference to a [`File`] from a valid pointer. |
| 349 | /// |
| 350 | /// # Safety |
| 351 | /// |
| 352 | /// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is |
| 353 | /// positive for the duration of `'a`. |
| 354 | /// * The caller must ensure that if there are active `fdget_pos` calls on this file, then they |
| 355 | /// took the `f_pos_lock` mutex. |
| 356 | |
| 357 | pub unsafe |
| 358 | // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the |
| 359 | // duration of `'a`. The cast is okay because `File` is `repr(transparent)`. |
| 360 | // |
| 361 | // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls. |
| 362 | unsafe |
| 363 | |
| 364 | |
| 365 | |
| 366 | // Make LocalFile methods available on File. |
| 367 | |
| 368 | type Target = LocalFile; |
| 369 | |
| 370 | |
| 371 | // SAFETY: The caller provides a `&File`, and since it is a reference, it must point at a |
| 372 | // valid file for the desired duration. |
| 373 | // |
| 374 | // By the type invariants, there are no `fdget_pos` calls that did not take the |
| 375 | // `f_pos_lock` mutex. |
| 376 | unsafe |
| 377 | |
| 378 | |
| 379 | |
| 380 | /// A file descriptor reservation. |
| 381 | /// |
| 382 | /// This allows the creation of a file descriptor in two steps: first, we reserve a slot for it, |
| 383 | /// then we commit or drop the reservation. The first step may fail (e.g., the current process ran |
| 384 | /// out of available slots), but commit and drop never fail (and are mutually exclusive). |
| 385 | /// |
| 386 | /// Dropping the reservation happens in the destructor of this type. |
| 387 | /// |
| 388 | /// # Invariants |
| 389 | /// |
| 390 | /// The fd stored in this struct must correspond to a reserved file descriptor of the current task. |
| 391 | |
| 392 | fd: u32, |
| 393 | /// Prevent values of this type from being moved to a different task. |
| 394 | /// |
| 395 | /// The `fd_install` and `put_unused_fd` functions assume that the value of `current` is |
| 396 | /// unchanged since the call to `get_unused_fd_flags`. By adding this marker to this type, we |
| 397 | /// prevent it from being moved across task boundaries, which ensures that `current` does not |
| 398 | /// change while this value exists. |
| 399 | _not_send: NotThreadSafe, |
| 400 | |
| 401 | |
| 402 | |
| 403 | /// Creates a new file descriptor reservation. |
| 404 | |
| 405 | |
| 406 | // SAFETY: FFI call, there are no safety requirements on `flags`. |
| 407 | let fd: i32 = unsafe ; |
| 408 | to_result?; |
| 409 | |
| 410 | Ok |
| 411 | fd: fd as u32, |
| 412 | _not_send: NotThreadSafe, |
| 413 | |
| 414 | |
| 415 | |
| 416 | /// Returns the file descriptor number that was reserved. |
| 417 | |
| 418 | |
| 419 | self.fd |
| 420 | |
| 421 | |
| 422 | /// Commits the reservation. |
| 423 | /// |
| 424 | /// The previously reserved file descriptor is bound to `file`. This method consumes the |
| 425 | /// [`FileDescriptorReservation`], so it will not be usable after this call. |
| 426 | |
| 427 | |
| 428 | // SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`. We have not yet used |
| 429 | // the fd, so it is still valid, and `current` still refers to the same task, as this type |
| 430 | // cannot be moved across task boundaries. |
| 431 | // |
| 432 | // Furthermore, the file pointer is guaranteed to own a refcount by its type invariants, |
| 433 | // and we take ownership of that refcount by not running the destructor below. |
| 434 | // Additionally, the file is known to not have any non-shared `fdget_pos` calls, so even if |
| 435 | // this process starts using the file position, this will not result in a data race on the |
| 436 | // file position. |
| 437 | unsafe ; |
| 438 | |
| 439 | // `fd_install` consumes both the file descriptor and the file reference, so we cannot run |
| 440 | // the destructors. |
| 441 | forget; |
| 442 | forget; |
| 443 | |
| 444 | |
| 445 | |
| 446 | |
| 447 | |
| 448 | |
| 449 | // SAFETY: By the type invariants of this type, `self.fd` was previously returned by |
| 450 | // `get_unused_fd_flags`. We have not yet used the fd, so it is still valid, and `current` |
| 451 | // still refers to the same task, as this type cannot be moved across task boundaries. |
| 452 | unsafe ; |
| 453 | |
| 454 | |
| 455 | |
| 456 | /// Represents the [`EBADF`] error code. |
| 457 | /// |
| 458 | /// Used for methods that can only fail with [`EBADF`]. |
| 459 | |
| 460 | ; |
| 461 | |
| 462 | |
| 463 | |
| 464 | |
| 465 | EBADF |
| 466 | |
| 467 | |
| 468 | |
| 469 | |
| 470 | |
| 471 | f.pad |
| 472 | |
| 473 |