initial import
[patches.git] / cryptsetup-1.0.6-svn-udev.patch
1 Index: lib/setup.c
2 ===================================================================
3 --- lib/setup.c (revision 29)
4 +++ lib/setup.c (revision 32)
5 @@ -396,7 +396,7 @@ static int __crypt_remove_device(int arg
6 return -EBUSY;
7 }
8
9 - return backend->remove(options);
10 + return backend->remove(0, options);
11 }
12
13 static int __crypt_luks_format(int arg, struct setup_backend *backend, struct crypt_options *options)
14 @@ -705,7 +705,10 @@ static int crypt_job(int (*job)(int arg,
15
16 backend = get_setup_backend(default_backend);
17
18 - setup_enter(backend,options->icb->log);
19 + if (setup_enter(backend,options->icb->log) < 0) {
20 + r = -ENOSYS;
21 + goto out;
22 + }
23
24 if (!backend) {
25 set_error("No setup backend available");
26 Index: lib/internal.h
27 ===================================================================
28 --- lib/internal.h (revision 29)
29 +++ lib/internal.h (revision 32)
30 @@ -40,7 +40,7 @@ struct setup_backend {
31 const char *key);
32 int (*status)(int details, struct crypt_options *options,
33 char **key);
34 - int (*remove)(struct crypt_options *options);
35 + int (*remove)(int force, struct crypt_options *options);
36
37 const char * (*dir)(void);
38 };
39 Index: lib/libdevmapper.c
40 ===================================================================
41 --- lib/libdevmapper.c (revision 29)
42 +++ lib/libdevmapper.c (revision 32)
43 @@ -17,13 +17,7 @@
44 #define DEVICE_DIR "/dev"
45
46 #define CRYPT_TARGET "crypt"
47 -
48 -#define UDEVSETTLE "/sbin/udevsettle"
49 -
50 -static void run_udevsettle(void)
51 -{
52 - system(UDEVSETTLE);
53 -}
54 +#define RETRY_COUNT 5
55
56 static void set_dm_error(int level, const char *file, int line,
57 const char *f, ...)
58 @@ -38,9 +32,16 @@ static void set_dm_error(int level, cons
59 va_end(va);
60 }
61
62 +static int _dm_simple(int task, const char *name);
63 +
64 static int dm_init(void)
65 {
66 dm_log_init(set_dm_error);
67 + if (!_dm_simple(DM_DEVICE_LIST_VERSIONS, "test")) {
68 + set_error("Cannot communicate with device-mapper. Is the dm_mod module loaded?");
69 + return -1;
70 + }
71 +
72 return 1; /* unsafe memory */
73 }
74
75 @@ -50,16 +51,6 @@ static void dm_exit(void)
76 dm_lib_release();
77 }
78
79 -static void flush_dm_workqueue(void)
80 -{
81 - /*
82 - * Unfortunately this is the only way to trigger libdevmapper's
83 - * update_nodes function
84 - */
85 - dm_exit();
86 - dm_init();
87 -}
88 -
89 static char *__lookup_dev(char *path, dev_t dev)
90 {
91 struct dirent *entry;
92 @@ -152,6 +143,89 @@ out:
93 return params;
94 }
95
96 +/* DM helpers */
97 +static int _dm_simple(int task, const char *name)
98 +{
99 + int r = 0;
100 + struct dm_task *dmt;
101 +
102 + if (!(dmt = dm_task_create(task)))
103 + return 0;
104 +
105 + if (!dm_task_set_name(dmt, name))
106 + goto out;
107 +
108 + r = dm_task_run(dmt);
109 +
110 + out:
111 + dm_task_destroy(dmt);
112 + return r;
113 +}
114 +
115 +static int _error_device(struct crypt_options *options)
116 +{
117 + struct dm_task *dmt;
118 + int r = 0;
119 +
120 + if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
121 + return 0;
122 +
123 + if (!dm_task_set_name(dmt, options->name))
124 + goto error;
125 +
126 + if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", ""))
127 + goto error;
128 +
129 + if (!dm_task_set_ro(dmt))
130 + goto error;
131 +
132 + if (!dm_task_no_open_count(dmt))
133 + goto error;
134 +
135 + if (!dm_task_run(dmt))
136 + goto error;
137 +
138 + if (!_dm_simple(DM_DEVICE_RESUME, options->name)) {
139 + _dm_simple(DM_DEVICE_CLEAR, options->name);
140 + goto error;
141 + }
142 +
143 + r = 1;
144 +
145 +error:
146 + dm_task_destroy(dmt);
147 + return r;
148 +}
149 +
150 +static int _dm_remove(struct crypt_options *options, int force)
151 +{
152 + int r = -EINVAL;
153 + int retries = force ? RETRY_COUNT : 1;
154 +
155 + /* If force flag is set, replace device with error, read-only target.
156 + * it should stop processes from reading it and also removed underlying
157 + * device from mapping, so it is usable again.
158 + * Force flag should be used only for temporary devices, which are
159 + * intended to work inside cryptsetup only!
160 + * Anyway, if some process try to read temporary cryptsetup device,
161 + * it is bug - no other process should try touch it (e.g. udev).
162 + */
163 + if (force) {
164 + _error_device(options);
165 + retries = RETRY_COUNT;
166 + }
167 +
168 + do {
169 + r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL;
170 + if (--retries)
171 + sleep(1);
172 + } while (r == -EINVAL && retries);
173 +
174 + dm_task_update_nodes();
175 +
176 + return r;
177 +}
178 +
179 static int dm_create_device(int reload, struct crypt_options *options,
180 const char *key)
181 {
182 @@ -191,24 +265,14 @@ static int dm_create_device(int reload,
183 if (dmi.read_only)
184 options->flags |= CRYPT_FLAG_READONLY;
185
186 - /* run udevsettle to avoid a race in libdevmapper causing busy dm devices */
187 - run_udevsettle();
188 -
189 r = 0;
190 -
191 out:
192 if (r < 0 && !reload) {
193 char *error = (char *)get_error();
194 if (error)
195 error = strdup(error);
196 - if (dmt)
197 - dm_task_destroy(dmt);
198
199 - if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
200 - goto out_restore_error;
201 - if (!dm_task_set_name(dmt, options->name))
202 - goto out_restore_error;
203 - if (!dm_task_run(dmt))
204 + if (!_dm_remove(options, 0))
205 goto out_restore_error;
206
207 out_restore_error:
208 @@ -224,7 +288,7 @@ out_no_removal:
209 dm_task_destroy(dmt);
210 if(dmt_query)
211 dm_task_destroy(dmt_query);
212 - flush_dm_workqueue();
213 + dm_task_update_nodes();
214 return r;
215 }
216
217 @@ -352,25 +416,12 @@ out:
218 return r;
219 }
220
221 -static int dm_remove_device(struct crypt_options *options)
222 +static int dm_remove_device(int force, struct crypt_options *options)
223 {
224 - struct dm_task *dmt;
225 - int r = -EINVAL;
226 -
227 - if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
228 - goto out;
229 - if (!dm_task_set_name(dmt, options->name))
230 - goto out;
231 - if (!dm_task_run(dmt))
232 - goto out;
233 -
234 - r = 0;
235 + if (!options || !options->name)
236 + return -EINVAL;
237
238 -out:
239 - if (dmt)
240 - dm_task_destroy(dmt);
241 - flush_dm_workqueue();
242 - return r;
243 + return _dm_remove(options, force);;
244 }
245
246
247 Index: luks/keyencryption.c
248 ===================================================================
249 --- luks/keyencryption.c (revision 29)
250 +++ luks/keyencryption.c (revision 32)
251 @@ -45,6 +45,11 @@ static inline int round_up_modulo(int x,
252 return div_round_up(x, m) * m;
253 }
254
255 +static struct setup_backend *cleaner_backend=NULL;
256 +static const char *cleaner_name=NULL;
257 +static uint64_t cleaner_size = 0;
258 +static int devfd=-1;
259 +
260 static int setup_mapping(const char *cipher, const char *name,
261 const char *device, unsigned int payloadOffset,
262 const char *key, size_t keyLength,
263 @@ -52,7 +57,7 @@ static int setup_mapping(const char *cip
264 struct setup_backend *backend,
265 int mode)
266 {
267 - struct crypt_options k;
268 + struct crypt_options k = {0};
269 struct crypt_options *options = &k;
270 int device_sector_size = sector_size_for_device(device);
271 int r;
272 @@ -66,6 +71,7 @@ static int setup_mapping(const char *cip
273 return -EINVAL;
274 }
275 options->size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
276 + cleaner_size = options->size;
277
278 options->offset = sector;
279 options->cipher = cipher;
280 @@ -87,24 +93,21 @@ static int setup_mapping(const char *cip
281 return r;
282 }
283
284 -static int clear_mapping(const char *name, struct setup_backend *backend)
285 +static int clear_mapping(const char *name, uint64_t size, struct setup_backend *backend)
286 {
287 - struct crypt_options options;
288 + struct crypt_options options = {0};
289 options.name=name;
290 - return backend->remove(&options);
291 + options.size = size;
292 + return backend->remove(1, &options);
293 }
294
295 -/* I miss closures in C! */
296 -static struct setup_backend *cleaner_backend=NULL;
297 -static const char *cleaner_name=NULL;
298 -static int devfd=0;
299 -
300 static void sigint_handler(int sig)
301 {
302 - if(devfd)
303 + if(devfd >= 0)
304 close(devfd);
305 + devfd = -1;
306 if(cleaner_backend && cleaner_name)
307 - clear_mapping(cleaner_name, cleaner_backend);
308 + clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
309 signal(SIGINT, SIG_DFL);
310 kill(getpid(), SIGINT);
311 }
312 @@ -160,13 +163,14 @@ static int LUKS_endec_template(char *src
313 r = 0;
314 out3:
315 close(devfd);
316 - devfd = 0;
317 + devfd = -1;
318 out2:
319 - clear_mapping(name,backend);
320 + clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
321 out1:
322 signal(SIGINT, SIG_DFL);
323 cleaner_name = NULL;
324 cleaner_backend = NULL;
325 + cleaner_size = 0;
326 free(dmCipherSpec);
327 free(fullpath);
328 free(name);