summaryrefslogtreecommitdiff
path: root/notes.txt
blob: 1e4f296147d08168ef4b6977a9001841b2b24cac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
initramfs-tools launches, as pid 1, a script called /init which is used to call
all of the various configured scripts which are installed into
'/etc/initramfs-tools/scripts'.

Some of this scripts are executed in subshells, thus they cannot contain the
final 'pivot_root' (or actually 'switch_root' now), but some of the scripts are
sourced from the pid1 'sh' process.

There is an environment variable called 'BOOT' which is set to 'local' by
default and which can be overriden on the kernel command line. The pid1 process
will source a file named with the value of the 'BOOT' variable:

    # Always load local and nfs (since these might be needed for /etc or
    # /usr, irrespective of the boot script used to mount the rootfs).
    . /scripts/local
    . /scripts/nfs
    . /scripts/${BOOT}

The BOOT script is used to define functions that will be called within pid1;
particularly (from '/scripts/local', for example):


    mountroot()
    {
      local_mount_root
    }

    mount_top()
    {
      # Note, also called directly in case it's overridden.
      local_top
    }

    mount_premount()
    {
      # Note, also called directly in case it's overridden.
      local_premount
    }

    mount_bottom()
    {
      # Note, also called directly in case it's overridden.
      local_bottom
    }


Thus, it should be possible to add a script '/script/samizdat' which overrides
one of these functions, and then add a BOOT=samizdat parameter.

(Note: the 'local' versions of these scripts merely call 'run_scripts' on
directories named like '/scripts/local-premount' etc. -- 'run_scripts' runs
scripts in new processes, it does not source them from pid 1. But see below.)

Almost certainly, the samizdat script should simply define the function 'mountroot'.

Note: if it was desired not to have to set a kernel parameter, it would also be
possible to 'trick' the system into executing code as pid1 through any script
called with 'run_scripts' (such as a file placed in '/scripts/local-bottom').

A script called with 'run_scripts' will run in a separate process, but after
each script is called, pid1 will source the file '/conf/param.conf'.

Thus, to overwrite the mountroot() function, something like this should suffice:

  cat > /conf/mountroot-override <<EOF

  mountroot()
  {
    # ...
  }
  EOF
  
  echo '. /conf/mountroot-override' >> /conf/param.conf

Or even just:

  echo BOOT=samizdat >> /conf/mountroot-override






This is probably the approach to take:

  Create two scripts:

    /etc/initramfs-tools/scripts/local-bottom/samizdat
    /etc/initramfs-tools/scripts/samizdat

  The first script just does:

      echo BOOT=samizdat         >> /conf/param.conf
  
  The second script calls out to the existing samizdat initrd code. It can even
  'exec' the original samizdat 'init', although it probably shouldn't.






Another idea:


  The first script waits for a samizdat read-only ISO, then configures the rest
  of the boot process:

    * Find the btrfs seed filesystem on the ISO
    * Mount it as a loop device
    * Add a ramfs to it, making it read-write
    * Chroot into this system and run code to interact with the user and determine what to do:
      * Find existing encrypted LUKS partitions
      * Find existing encrypted GPG keys
      * Allow the user to decrypt GPG keys -- saving the password in order to restart GPG agent
      * Allow the user to create a new LUKS partition or choose an existing one
    * If successful:

      echo BOOT=samizdat         >> /conf/param.conf
      echo SAMIZDAT_LUKS_DEV=... >> /conf/param.conf   # unencrypted dm dev
      echo SAMIZDAT_GPG_ID=...   >> /conf/param.conf   # record the user we've authenticated as
    
  The second script does the rest of the work:
  
    * ...















grepping for param.conf:

/usr/share/initramfs-tools/scripts/local-top/cryptroot:			# Apparently ROOT is already set in /conf/param.conf for
/usr/share/initramfs-tools/scripts/local-top/cryptroot:			if [ -f /conf/param.conf ] && grep -q "^ROOT=" /conf/param.conf; then
/usr/share/initramfs-tools/scripts/local-top/cryptroot:				NEWROOT=$(sed -n 's/^ROOT=//p' /conf/param.conf)
/usr/share/initramfs-tools/scripts/local-top/cryptroot:					echo "ROOT=$NEWROOT" >>/conf/param.conf
/usr/share/initramfs-tools/hook-functions:		echo "[ -e /conf/param.conf ] && . /conf/param.conf" >> ${initdir}/ORDER
/usr/share/initramfs-tools/hook-functions:		if [ -e /conf/param.conf ]; then
/usr/share/initramfs-tools/hook-functions:			. /conf/param.conf

Relevant instances of 'run_scripts':

      Definition:

        /usr/share/initramfs-tools/scripts/functions:run_scripts()

      Uses in pid1:

        /usr/share/initramfs-tools/init:run_scripts /scripts/init-top
        /usr/share/initramfs-tools/init:run_scripts /scripts/init-premount
        /usr/share/initramfs-tools/init:run_scripts /scripts/init-bottom

      Uses in 'local':

        /usr/share/initramfs-tools/scripts/local:		run_scripts /scripts/local-top
        /usr/share/initramfs-tools/scripts/local:	run_scripts /scripts/local-block "$@"
        /usr/share/initramfs-tools/scripts/local:		run_scripts /scripts/local-premount
        /usr/share/initramfs-tools/scripts/local:		run_scripts /scripts/local-bottom
      
        Note that 'local' is unconditionally executed in init:
        


      Panic hooks:

        /usr/share/initramfs-tools/scripts/functions:	run_scripts /scripts/panic