process.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! Types and functions related to child processes management.
  5. use crate::Env;
  6. use std::path::PathBuf;
  7. #[cfg(feature = "command")]
  8. #[cfg_attr(doc_cfg, doc(cfg(feature = "command")))]
  9. mod command;
  10. #[cfg(feature = "command")]
  11. #[cfg_attr(doc_cfg, doc(cfg(feature = "command")))]
  12. pub use command::*;
  13. /// Finds the current running binary's path.
  14. ///
  15. /// # Platform-specific behavior
  16. ///
  17. /// On the `Linux` platform, this function will also **attempt** to detect if
  18. /// it's currently running from a valid [AppImage] and use that path instead.
  19. ///
  20. /// # Security
  21. ///
  22. /// If the above Platform-specific behavior does not take place, this function
  23. /// uses [`std::env::current_exe`]. Notably, it also has a security section
  24. /// that goes over a theoretical attack using hard links. Let's cover some
  25. /// specific topics that relate to different ways an attacker might try to
  26. /// trick this function into returning the wrong binary path.
  27. ///
  28. /// ## Symlinks ("Soft Links")
  29. ///
  30. /// [`std::path::Path::canonicalize`] is used to resolve symbolic links to the
  31. /// original path, including nested symbolic links (`link2 -> link1 -> bin`).
  32. ///
  33. /// ## Hard Links
  34. ///
  35. /// A [Hard Link] is a named entry that points to a file in the file system.
  36. /// On most systems, this is what you would think of as a "file". The term is
  37. /// used on filesystems that allow multiple entries to point to the same file.
  38. /// The linked [Hard Link] Wikipedia page provides a decent overview.
  39. ///
  40. /// In short, unless the attacker was able to create the link with elevated
  41. /// permissions, it should generally not be possible for them to hard link
  42. /// to a file they do not have permissions to - with exception to possible
  43. /// operating system exploits.
  44. ///
  45. /// There are also some platform-specific information about this below.
  46. ///
  47. /// ### Windows
  48. ///
  49. /// Windows requires a permission to be set for the user to create a symlink
  50. /// or a hard link, regardless of ownership status of the target. Elevated
  51. /// permissions users have the ability to create them.
  52. ///
  53. /// ### macOS
  54. ///
  55. /// macOS allows for the creation of symlinks and hard links to any file.
  56. /// Accessing through those links will fail if the user who owns the links
  57. /// does not have the proper permissions on the original file.
  58. ///
  59. /// ### Linux
  60. ///
  61. /// Linux allows for the creation of symlinks to any file. Accessing the
  62. /// symlink will fail if the user who owns the symlink does not have the
  63. /// proper permissions on the original file.
  64. ///
  65. /// Linux additionally provides a kernel hardening feature since version
  66. /// 3.6 (30 September 2012). Most distributions since then have enabled
  67. /// the protection (setting `fs.protected_hardlinks = 1`) by default, which
  68. /// means that a vast majority of desktop Linux users should have it enabled.
  69. /// **The feature prevents the creation of hardlinks that the user does not own
  70. /// or have read/write access to.** [See the patch that enabled this.](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=800179c9b8a1e796e441674776d11cd4c05d61d7)
  71. ///
  72. /// [AppImage]: https://appimage.org/
  73. /// [Hard Link]: https://en.wikipedia.org/wiki/Hard_link
  74. #[allow(unused_variables)]
  75. pub fn current_binary(env: &Env) -> Option<PathBuf> {
  76. // if we are running from an AppImage, we ONLY want the set AppImage path
  77. #[cfg(target_os = "linux")]
  78. if let Some(app_image_path) = &env.appimage {
  79. return Some(PathBuf::from(app_image_path));
  80. }
  81. // see https://doc.rust-lang.org/std/env/fn.current_exe.html#security for
  82. // an example of what to be careful of when using `current_exe` output.
  83. std::env::current_exe()
  84. .ok()
  85. // we canonicalize the path we received from `current_exe` to resolve any
  86. // soft links. it avoids the usual issue of needing the file to exist at
  87. // the passed path because a valid `current_exe` result should always exist
  88. .and_then(|path| path.canonicalize().ok())
  89. }
  90. /// Restarts the process.
  91. ///
  92. /// See [`current_binary`] for the possible security implications.
  93. pub fn restart(env: &Env) {
  94. use std::process::{exit, Command};
  95. if let Some(path) = current_binary(env) {
  96. Command::new(path)
  97. .spawn()
  98. .expect("application failed to start");
  99. }
  100. exit(0);
  101. }