crypt_reboot 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca95c9301674a1698f766dbfa5dfd06adc99e91a286c32b7eaa77d8611e21762
4
- data.tar.gz: 5403a4ed739f8b5901451e3e413598e85acfee1765266a66d85257c708904399
3
+ metadata.gz: ee0a1d8c466f902cc47c84b3310c899046ae2d2cacc952f184baa76463add807
4
+ data.tar.gz: 6fc17834b241d0822848b84e36fa2277b47a998c77659740a82d0e49d83a16e6
5
5
  SHA512:
6
- metadata.gz: d633a85afa5dc298f39c144d700347cb20ae4bc03e5865ba3a92c2a1ae0ec9bc679393b612f7c18838d35578f583db8f791aab223f896a1ed3fce8bcfd78c6e8
7
- data.tar.gz: 59442b7e7106a5d2892def87930503472315dbc45da8d9bf8919d29fc7fc998edcb2dfe69b3bc4ea0306c173bc1dc305fa5be42954bb706eb35f4104531933a3
6
+ metadata.gz: 030a74f06349d21c91b05a7ac297ffb927309faad863689a8cd632521587e47059c38995b377e199e5337819f447999796f65aa6dfa17345f7aaca0821458a23
7
+ data.tar.gz: 2f16596ee0b871ecec49b9687da65d3086c66daa41b48e3090d43317452755752443996f5ef5887ac4a73f50f31bd4307ab08254b2869e3219970117ddfcbeee
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.1.2] - 2023-07-22
2
+
3
+ - Lock memory to prevent secrets leaking to swap
4
+ - Use `ramfs` instead of `tmpfs` for the same reason
5
+
6
+ ## [0.1.1] - 2023-07-13
7
+
8
+ - Standardize passphrase prompt
9
+
1
10
  ## [0.1.0] - 2023-07-09
2
11
 
3
12
  - Initial release
data/README.md CHANGED
@@ -28,13 +28,16 @@ Debian, Ubuntu, Linux Mint, Pop!_OS, etc.
28
28
  On the other hand, do not expect it to work on other distributions now.
29
29
  But support for them may come in upcoming versions.
30
30
 
31
- Following distributions were tested by the author:
31
+ Following distributions were tested by the author on the AMD64 machine:
32
+ - DappNode 0.2.75 is based on Debian 12, see below
33
+ - Debian 12 needs [symlinks for kernel and initramfs](#no-symlinks-to-most-recent-kernel-and-initramfs)
34
+ - Pop!_OS 22.04 LTS
35
+ - Ubuntu 23.04
32
36
  - Ubuntu 22.04 LTS
33
37
  - Ubuntu 20.04 LTS needs tiny adjustments to system settings,
34
38
  specifically [changing compression](#lz4-initramfs-compression) and
35
39
  [fixing systemd kexec support](#staged-kernel-not-being-executed-by-systemd)
36
40
  - ~~Ubuntu 18.04 LTS~~ is not supported (initramfs uses *pre-crypttab* format)
37
- - Pop!_OS 22.04 LTS
38
41
 
39
42
  If you have successfully run cryptreboot on another distribution,
40
43
  please contact me and I will update the list.
@@ -50,17 +53,36 @@ You need to ensure those are installed:
50
53
  If you use recent, mainstream Linux distribution, other requirements are
51
54
  probably already met:
52
55
  - `kexec` support in the kernel
53
- - `tmpfs` filesystem support in kernel
56
+ - `ramfs` filesystem support in kernel
54
57
  - `cryptsetup` (if you use disk encryption, it should be installed)
55
58
  - `systemd` or another way to guarantee staged kernel is executed on reboot
56
59
  - `strace` (not required if `--skip-lz4-check` flag is specified)
57
60
 
61
+ If you use Debian-based distribution, use this command to install required packages:
62
+
63
+ $ sudo apt install --no-install-recommends cryptsetup-initramfs kexec-tools ruby strace systemd
64
+
65
+ When asked if kexec should handle reboots, answer `yes` (however the answer probably
66
+ doesn't matter for cryptreboot to work).
67
+
68
+ ## Recommendations
69
+
70
+ To protects against saving sensitive data (passphrase, encryption keys) to swap space on a disk, it is recommended to use `memory_locker` ([Rubygems](https://rubygems.org/gems/memory_locker), [Github](https://github.com/phantom-node/memory_locker)).
71
+
72
+ $ sudo gem install memory_locker
73
+
74
+ If you don't want to install it, you will have to specify `--insecure-memory` flag when running cryptreboot.
75
+
58
76
  ## Installation
59
77
 
60
78
  Make sure the required software is installed, then install the gem system-wide by executing:
61
79
 
62
80
  $ sudo gem install crypt_reboot
63
81
 
82
+ To upgrade run:
83
+
84
+ $ sudo gem update crypt_reboot
85
+
64
86
  ## Usage
65
87
 
66
88
  Cryptreboot performs operations normally only available to the root user,
@@ -74,7 +96,7 @@ To see the usage, run:
74
96
 
75
97
  $ cryptreboot --help
76
98
 
77
- ## Resolutions for common issues
99
+ ## Troubleshooting
78
100
 
79
101
  ### LZ4 initramfs compression
80
102
 
@@ -130,6 +152,40 @@ To cancel the change, remove the file:
130
152
 
131
153
  $ sudo rm /etc/systemd/system/systemd-kexec.service.d/override.conf
132
154
 
155
+ ### No symlinks to the most recent kernel and initramfs
156
+
157
+ By default, cryptreboot looks for kernel in `/boot/vmlinuz` and for initramfs
158
+ in `/boot/initrd.img`. If those files are missing in your Linux distribution,
159
+ cryptreboot will fail, unless you use `--kernel` and `--initramfs` command line
160
+ options.
161
+
162
+ $ sudo cryptreboot --kernel /boot/vmlinuz-`uname -r` --initramfs /boot/initrd.img-`uname -r`
163
+
164
+ If you don't want to specify options every time you reboot, add symlinks to
165
+ the currently running kernel and initramfs:
166
+
167
+ $ cd /boot
168
+ $ sudo ln -sf vmlinuz-`uname -r` vmlinuz
169
+ $ sudo ln -sf initrd.img-`uname -r` initrd.img
170
+
171
+ Unfortunately, you need to rerun it after each kernel upgrade, otherwise,
172
+ cryptreboot is going to boot the old kernel.
173
+ Upcoming versions of cryptreboot will offer better solutions.
174
+
175
+ ### Problems with memory locking
176
+
177
+ If you get:
178
+
179
+ > Locking error: Failed to lock memory
180
+
181
+ it means there was an error while locking memory to prevent a risk of sensitive data ending in a swap space.
182
+
183
+ The best solution is to install `memory_locker` (see [requirements](#requirements) section).
184
+ If it still doesn't help, make sure you have permission to lock memory. Root users do.
185
+ If the problem persists, then please report a bug describing your setup.
186
+
187
+ The solution of last resort is to use `--insecure-memory` flag, which disables memory locking completely.
188
+
133
189
  ## Development
134
190
 
135
191
  After checking out the repo, run `bundle install` to install
data/lib/basic_loader.rb CHANGED
@@ -8,6 +8,7 @@ require 'crypt_reboot/cli'
8
8
  require 'crypt_reboot/concatenator'
9
9
  require 'crypt_reboot/instantiable_config'
10
10
  require 'crypt_reboot/config'
11
+ require 'crypt_reboot/elastic_memory_locker'
11
12
  require 'crypt_reboot/files_generator'
12
13
  require 'crypt_reboot/files_writer'
13
14
  require 'crypt_reboot/gziper'
@@ -90,6 +90,12 @@ module CryptReboot
90
90
  'algorithm to a more robust one.'
91
91
  end
92
92
 
93
+ flag :insecure_memory do
94
+ short '-s'
95
+ long '--insecure-memory'
96
+ desc 'Do not lock memory. WARNING: there is a risk your secrets will leak to swap.'
97
+ end
98
+
93
99
  flag :debug do
94
100
  short '-d'
95
101
  long '--debug'
@@ -7,7 +7,7 @@ module CryptReboot
7
7
  def call(raw_params)
8
8
  params = parser.call(raw_params)
9
9
  handle_action_params!(params) or configure_and_exec(params)
10
- rescue StandardError => e
10
+ rescue StandardError, Interrupt => e
11
11
  raise if debug?
12
12
 
13
13
  sad_exiter_class.new(error_message(e))
@@ -21,6 +21,7 @@ module CryptReboot
21
21
 
22
22
  def configure_and_exec(params)
23
23
  config_updater.call(**params)
24
+ locker.call
24
25
  loader.call
25
26
  rebooter
26
27
  end
@@ -45,7 +46,7 @@ module CryptReboot
45
46
 
46
47
  attr_reader :parser, :config_updater, :loader, :help_generator,
47
48
  :version_string, :debug_checker, :rebooter,
48
- :happy_exiter_class, :sad_exiter_class
49
+ :happy_exiter_class, :sad_exiter_class, :locker
49
50
 
50
51
  # rubocop:disable Metrics/ParameterLists
51
52
  def initialize(parser: Params::Parser.new,
@@ -56,7 +57,8 @@ module CryptReboot
56
57
  debug_checker: LazyConfig.debug,
57
58
  rebooter: Rebooter.new,
58
59
  happy_exiter_class: HappyExiter,
59
- sad_exiter_class: SadExiter)
60
+ sad_exiter_class: SadExiter,
61
+ locker: ElasticMemoryLocker.new)
60
62
  @parser = parser
61
63
  @config_updater = config_updater
62
64
  @loader = loader
@@ -66,6 +68,7 @@ module CryptReboot
66
68
  @rebooter = rebooter
67
69
  @happy_exiter_class = happy_exiter_class
68
70
  @sad_exiter_class = sad_exiter_class
71
+ @locker = locker
69
72
  end
70
73
  # rubocop:enable Metrics/ParameterLists
71
74
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CryptReboot
4
+ # Try to lock memory if configuration allows it
5
+ class ElasticMemoryLocker
6
+ LockingError = Class.new StandardError
7
+
8
+ def call
9
+ return if skip_locking?
10
+
11
+ loader.call
12
+ locker.call
13
+ nil
14
+ rescue load_error, locking_error => e
15
+ raise LockingError, 'Failed to lock memory', cause: e
16
+ end
17
+
18
+ private
19
+
20
+ def skip_locking?
21
+ insecure_memory_checker.call
22
+ end
23
+
24
+ def locking_error
25
+ lazy_locking_error.call
26
+ end
27
+
28
+ attr_reader :insecure_memory_checker, :loader, :load_error, :locker, :lazy_locking_error
29
+
30
+ def initialize(insecure_memory_checker: LazyConfig.insecure_memory,
31
+ loader: -> { require 'memory_locker' },
32
+ load_error: LoadError,
33
+ locker: -> { MemoryLocker.call },
34
+ lazy_locking_error: -> { MemoryLocker::Error })
35
+ @insecure_memory_checker = insecure_memory_checker
36
+ @loader = loader
37
+ @load_error = load_error
38
+ @locker = locker
39
+ @lazy_locking_error = lazy_locking_error
40
+ end
41
+ end
42
+ end
@@ -8,7 +8,7 @@ module CryptReboot
8
8
  attr_reader :initramfs, :cmdline, :kernel, :patch_save_path, :cat_path, :cpio_path,
9
9
  :unmkinitramfs_path, :kexec_path, :cryptsetup_path, :reboot_path,
10
10
  :mount_path, :umount_path, :strace_path, :grep_path,
11
- :debug, :prepare_only, :skip_lz4_check
11
+ :debug, :prepare_only, :skip_lz4_check, :insecure_memory
12
12
 
13
13
  def update!(**settings)
14
14
  settings.each do |name, value|
@@ -25,6 +25,7 @@ module CryptReboot
25
25
  end
26
26
 
27
27
  # rubocop:disable Metrics/MethodLength
28
+ # rubocop:disable Metrics/AbcSize
28
29
  def initialize
29
30
  # Options
30
31
  @initramfs = '/boot/initrd.img'
@@ -46,7 +47,9 @@ module CryptReboot
46
47
  @debug = false
47
48
  @prepare_only = false
48
49
  @skip_lz4_check = false
50
+ @insecure_memory = false
49
51
  end
52
+ # rubocop:enable Metrics/AbcSize
50
53
  # rubocop:enable Metrics/MethodLength
51
54
  end
52
55
  end
@@ -4,7 +4,7 @@ require 'tmpdir'
4
4
 
5
5
  module CryptReboot
6
6
  module SafeTemp
7
- # Create temporary directory, mounts tmpfs and yields tmp dir location.
7
+ # Create temporary directory, mounts ramfs and yields tmp dir location.
8
8
  # Make sure to cleanup afterwards.
9
9
  class Directory
10
10
  def call
@@ -2,7 +2,9 @@
2
2
 
3
3
  module CryptReboot
4
4
  module SafeTemp
5
- # Mount tmpfs at the given mount point, yield and unmount
5
+ # Mount ramfs at the given mount point, yield and unmount.
6
+ # We don't want the contents of directory to be swapped,
7
+ # therefore ramfs is used instead of tmpfs.
6
8
  class Mounter
7
9
  def call(dir, &block)
8
10
  mounter.call(dir)
@@ -21,7 +23,7 @@ module CryptReboot
21
23
 
22
24
  def initialize(runner: Runner::NoResult.new,
23
25
  mounter: lambda { |dir|
24
- runner.call(Config.mount_path, '-t', 'tmpfs', '-o', 'mode=700', 'none', dir)
26
+ runner.call(Config.mount_path, '-t', 'ramfs', '-o', 'mode=700', 'none', dir)
25
27
  },
26
28
  umounter: ->(dir) { runner.call(Config.umount_path, dir) })
27
29
  @runner = runner
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CryptReboot
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/crypt_reboot.rb CHANGED
@@ -7,6 +7,7 @@ rescue LoadError => e
7
7
 
8
8
  require 'zeitwerk'
9
9
  loader = Zeitwerk::Loader.for_gem
10
+ loader.ignore("#{__dir__}/memory_locker.rb") # stub has to be loaded manually
10
11
  loader.setup
11
12
  end
12
13
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crypt_reboot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paweł Pokrywka
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-13 00:00:00.000000000 Z
11
+ date: 2023-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-command
@@ -71,6 +71,7 @@ files:
71
71
  - lib/crypt_reboot/crypt_tab/keyfile_locator.rb
72
72
  - lib/crypt_reboot/crypt_tab/luks_to_plain_converter.rb
73
73
  - lib/crypt_reboot/crypt_tab/serializer.rb
74
+ - lib/crypt_reboot/elastic_memory_locker.rb
74
75
  - lib/crypt_reboot/files_generator.rb
75
76
  - lib/crypt_reboot/files_writer.rb
76
77
  - lib/crypt_reboot/gziper.rb