crypt_reboot 0.1.2 → 0.2.1

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: 90456cf783f95d79186882a7fce00b153b4ff1928a68efd4609fb7e8859d3b04
4
- data.tar.gz: d5fd15cb6705793a7e357666158eaa4f95f5c14d41b22b1d82d087a921fa512c
3
+ metadata.gz: 6ec1b79f3b99fddc49e170693df471d0eebc44af064787cb29b2694985a91418
4
+ data.tar.gz: e3fa5ac025fc7ea7544a6e4c6d9db1f5894a0da44b6c39d07689a7594c0fc714
5
5
  SHA512:
6
- metadata.gz: 5c99c3e114727a1236ef3dd9f536a56b1a89639c4447f6387ec5bcd1bd25234f2655a75f306ace56dd78c36a0aadf77da4321ed6626c36c63e38c9852fefefea
7
- data.tar.gz: 37acfc427190670ad362cfb60a8a18ed29bcab338d24ac728ac23f4e3934c6669175db7872836ac46211d09dd16cba861259ec8e99c829050c1a8a3b875b9724
6
+ metadata.gz: 8aebba8307469fc4cba898f0c3427b4c6242e7f90dea985b33a72e89e13ee7e0854b232870b1afaea518c92eee03dca8c32d4c1f956a6da2e6cd55adae67f07e
7
+ data.tar.gz: 56d86831971b547b4d1856b426dafac2a77bffa23fd8ced861908902ce969186be52710e92dd50ec01242c77133d77439a088a651626dd9e8ce2977ce136483a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.2.1] - 2023-11-12
2
+
3
+ - use new MemoryLocker without a need for FFI compilation step
4
+
5
+ ## [0.2.0] - 2023-07-29
6
+
7
+ - Make memory locking optional with `--insecure-memory` command line option
8
+ - Remove FFI gem dependency
9
+
1
10
  ## [0.1.2] - 2023-07-22
2
11
 
3
12
  - Lock memory to prevent secrets leaking to swap
data/README.md CHANGED
@@ -7,7 +7,8 @@ Convenient reboot for Linux systems with encrypted root partition.
7
7
  > Just type `cryptreboot` instead of `reboot`.
8
8
 
9
9
  It asks for a passphrase and reboots the system afterward, automatically
10
- unlocking the drive on startup using in-memory initramfs patching and kexec.
10
+ unlocking the drive on startup using
11
+ [in-memory initramfs patching and kexec](https://blog.pawelpokrywka.com/p/rebooting-linux-with-encrypted-disk).
11
12
  Without explicit consent, no secrets are stored on disk, even temporarily.
12
13
 
13
14
  Useful when unlocking the drive at startup is difficult, such as on headless
@@ -36,7 +37,8 @@ Following distributions were tested by the author on the AMD64 machine:
36
37
  - Ubuntu 22.04 LTS
37
38
  - Ubuntu 20.04 LTS needs tiny adjustments to system settings,
38
39
  specifically [changing compression](#lz4-initramfs-compression) and
39
- [fixing systemd kexec support](#staged-kernel-not-being-executed-by-systemd)
40
+ [fixing systemd kexec support](#staged-kernel-not-being-executed-by-systemd), but still
41
+ [sometimes](#unable-to-kexec-on-reboot-using-old-systemd) reboot experience may be suboptimal
40
42
  - ~~Ubuntu 18.04 LTS~~ is not supported (initramfs uses *pre-crypttab* format)
41
43
 
42
44
  If you have successfully run cryptreboot on another distribution,
@@ -71,6 +73,10 @@ Make sure the required software is installed, then install the gem system-wide b
71
73
 
72
74
  $ sudo gem install crypt_reboot
73
75
 
76
+ To upgrade run:
77
+
78
+ $ sudo gem update crypt_reboot
79
+
74
80
  ## Usage
75
81
 
76
82
  Cryptreboot performs operations normally only available to the root user,
@@ -84,7 +90,7 @@ To see the usage, run:
84
90
 
85
91
  $ cryptreboot --help
86
92
 
87
- ## Resolutions for common issues
93
+ ## Troubleshooting
88
94
 
89
95
  ### LZ4 initramfs compression
90
96
 
@@ -140,9 +146,9 @@ To cancel the change, remove the file:
140
146
 
141
147
  $ sudo rm /etc/systemd/system/systemd-kexec.service.d/override.conf
142
148
 
143
- ### No symlinks to most recent kernel and initramfs
149
+ ### No symlinks to the most recent kernel and initramfs
144
150
 
145
- By default cryptreboot looks for kernel in `/boot/vmlinuz` and for initramfs
151
+ By default, cryptreboot looks for kernel in `/boot/vmlinuz` and for initramfs
146
152
  in `/boot/initrd.img`. If those files are missing in your Linux distribution,
147
153
  cryptreboot will fail, unless you use `--kernel` and `--initramfs` command line
148
154
  options.
@@ -160,6 +166,42 @@ Unfortunately, you need to rerun it after each kernel upgrade, otherwise,
160
166
  cryptreboot is going to boot the old kernel.
161
167
  Upcoming versions of cryptreboot will offer better solutions.
162
168
 
169
+ ### Problems with memory locking
170
+
171
+ If you get:
172
+
173
+ > Locking error: Failed to lock memory
174
+
175
+ it means there was an error while locking memory to prevent a risk of sensitive data ending in a swap space.
176
+
177
+ Make sure you have permission to lock memory. Root users have.
178
+ If permissions are ok, then please report a bug describing your setup.
179
+
180
+ The solution of last resort is to use `--insecure-memory` flag, which disables memory locking completely.
181
+
182
+ ### Unable to kexec on reboot using old systemd
183
+
184
+ Ubuntu 20.04 ships with `systemd` which may fall back to standard reboot instead of using `kexec`, because this utility
185
+ is located on a filesystem being unmounted during the shutdown sequence.
186
+
187
+ As a result, using cryptreboot would feel like using normal reboot.
188
+
189
+ To tell if your system is affected, you have to check messages printed to the console after you run cryptreboot.
190
+ This message happens just before reboot, so you will have just a few milliseconds to notice it on screen:
191
+
192
+ > shutdown[1]: (sd-kexec) failed with exit status 1
193
+
194
+ [There is a fix](https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1969365) waiting to be included in
195
+ a stable release update to `systemd` since 2023-07-21.
196
+
197
+ In the meantime, as a workaround, you can use `kexec` directly. **Warning: it will skip the standard shutdown procedure. Filesystems won't be unmounted, services won't be stopped, etc. It is like hitting `reset` button**.
198
+ However, when you use a decent filesystem with journalling the risk of things going bad should not be high.
199
+
200
+ Given the above warning, to reboot skipping the shutdown procedure, run:
201
+
202
+ $ sudo cryptreboot -p
203
+ $ sudo kexec -e # will skip proper shutdown sequence
204
+
163
205
  ## Development
164
206
 
165
207
  After checking out the repo, run `bundle install` to install
data/lib/basic_loader.rb CHANGED
@@ -8,13 +8,13 @@ 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'
14
15
  require 'crypt_reboot/initramfs_patch_squeezer'
15
16
  require 'crypt_reboot/kexec_patching_loader'
16
17
  require 'crypt_reboot/lazy_config'
17
- require 'crypt_reboot/memory_locker'
18
18
  require 'crypt_reboot/passphrase_asker'
19
19
  require 'crypt_reboot/patched_initramfs_generator'
20
20
  require 'crypt_reboot/rebooter'
@@ -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'
@@ -5,7 +5,6 @@ module CryptReboot
5
5
  # Interprets parameters, executes everything and returns callable object
6
6
  class ParamsParsingExecutor
7
7
  def call(raw_params)
8
- locker.call
9
8
  params = parser.call(raw_params)
10
9
  handle_action_params!(params) or configure_and_exec(params)
11
10
  rescue StandardError, Interrupt => e
@@ -22,6 +21,7 @@ module CryptReboot
22
21
 
23
22
  def configure_and_exec(params)
24
23
  config_updater.call(**params)
24
+ locker.call
25
25
  loader.call
26
26
  rebooter
27
27
  end
@@ -58,7 +58,7 @@ module CryptReboot
58
58
  rebooter: Rebooter.new,
59
59
  happy_exiter_class: HappyExiter,
60
60
  sad_exiter_class: SadExiter,
61
- locker: MemoryLocker.new)
61
+ locker: ElasticMemoryLocker.new)
62
62
  @parser = parser
63
63
  @config_updater = config_updater
64
64
  @loader = loader
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'memory_locker' unless defined? MemoryLocker # MemoryLocker is mocked in tests
4
+
5
+ module CryptReboot
6
+ # Try to lock memory if configuration allows it
7
+ class ElasticMemoryLocker
8
+ LockingError = Class.new StandardError
9
+
10
+ def call
11
+ return if skip_locking?
12
+
13
+ locker.call
14
+ nil
15
+ rescue locking_error => e
16
+ raise LockingError, 'Failed to lock memory', cause: e
17
+ end
18
+
19
+ private
20
+
21
+ def skip_locking?
22
+ insecure_memory_checker.call
23
+ end
24
+
25
+ attr_reader :insecure_memory_checker, :locker, :locking_error
26
+
27
+ def initialize(insecure_memory_checker: LazyConfig.insecure_memory,
28
+ locker: MemoryLocker,
29
+ locking_error: MemoryLocker::Error)
30
+ @insecure_memory_checker = insecure_memory_checker
31
+ @locker = locker
32
+ @locking_error = locking_error
33
+ end
34
+ end
35
+ 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CryptReboot
4
- VERSION = '0.1.2'
4
+ VERSION = '0.2.1'
5
5
  end
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.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paweł Pokrywka
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-22 00:00:00.000000000 Z
11
+ date: 2023-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-command
@@ -39,20 +39,20 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.3'
41
41
  - !ruby/object:Gem::Dependency
42
- name: ffi
42
+ name: memory_locker
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
47
+ version: 1.0.3
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.0
55
- description:
54
+ version: 1.0.3
55
+ description:
56
56
  email:
57
57
  - pepawel@users.noreply.github.com
58
58
  executables:
@@ -85,6 +85,7 @@ files:
85
85
  - lib/crypt_reboot/crypt_tab/keyfile_locator.rb
86
86
  - lib/crypt_reboot/crypt_tab/luks_to_plain_converter.rb
87
87
  - lib/crypt_reboot/crypt_tab/serializer.rb
88
+ - lib/crypt_reboot/elastic_memory_locker.rb
88
89
  - lib/crypt_reboot/files_generator.rb
89
90
  - lib/crypt_reboot/files_writer.rb
90
91
  - lib/crypt_reboot/gziper.rb
@@ -107,7 +108,6 @@ files:
107
108
  - lib/crypt_reboot/luks/dumper/luks_v2_parser.rb
108
109
  - lib/crypt_reboot/luks/key_fetcher.rb
109
110
  - lib/crypt_reboot/luks/version_detector.rb
110
- - lib/crypt_reboot/memory_locker.rb
111
111
  - lib/crypt_reboot/passphrase_asker.rb
112
112
  - lib/crypt_reboot/patched_initramfs_generator.rb
113
113
  - lib/crypt_reboot/rebooter.rb
@@ -131,7 +131,7 @@ metadata:
131
131
  source_code_uri: https://github.com/phantom-node/cryptreboot
132
132
  changelog_uri: https://github.com/phantom-node/cryptreboot/blob/master/CHANGELOG.md
133
133
  rubygems_mfa_required: 'true'
134
- post_install_message:
134
+ post_install_message:
135
135
  rdoc_options: []
136
136
  require_paths:
137
137
  - lib
@@ -146,8 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  - !ruby/object:Gem::Version
147
147
  version: '0'
148
148
  requirements: []
149
- rubygems_version: 3.1.6
150
- signing_key:
149
+ rubygems_version: 3.2.22
150
+ signing_key:
151
151
  specification_version: 4
152
152
  summary: Linux utility for automatic and secure unlocking of encrypted disks on reboot
153
153
  test_files: []
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ffi'
4
-
5
- module CryptReboot
6
- # Lock process memory, so it won't be swapped by the kernel.
7
- # It is implemented as a one-way operation: there is no unlock.
8
- # That's because it's hard to properly clean memory in Ruby.
9
- class MemoryLocker
10
- Error = Class.new StandardError
11
-
12
- def call
13
- return if Libc.mlockall(Libc::MCL_CURRENT | Libc::MCL_FUTURE).zero?
14
-
15
- raise Error, "Failed to lock memory: #{FFI.errno}"
16
- end
17
-
18
- # Low level interface to libc
19
- module Libc
20
- extend FFI::Library
21
- ffi_lib 'libc.so.6'
22
-
23
- # define mlockall constants
24
- MCL_CURRENT = 1
25
- MCL_FUTURE = 2
26
- MCL_ONFAULT = 4
27
-
28
- # declare mlockall function
29
- attach_function :mlockall, [:int], :int
30
- end
31
- private_constant :Libc
32
- end
33
- end