dm-ima.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 Microsoft Corporation
  4. *
  5. * Author: Tushar Sugandhi <[email protected]>
  6. *
  7. * File: dm-ima.c
  8. * Enables IMA measurements for DM targets
  9. */
  10. #include "dm-core.h"
  11. #include "dm-ima.h"
  12. #include <linux/ima.h>
  13. #include <linux/sched/mm.h>
  14. #include <crypto/hash.h>
  15. #include <linux/crypto.h>
  16. #include <crypto/hash_info.h>
  17. #define DM_MSG_PREFIX "ima"
  18. /*
  19. * Internal function to prefix separator characters in input buffer with escape
  20. * character, so that they don't interfere with the construction of key-value pairs,
  21. * and clients can split the key1=val1,key2=val2,key3=val3; pairs properly.
  22. */
  23. static void fix_separator_chars(char **buf)
  24. {
  25. int l = strlen(*buf);
  26. int i, j, sp = 0;
  27. for (i = 0; i < l; i++)
  28. if ((*buf)[i] == '\\' || (*buf)[i] == ';' || (*buf)[i] == '=' || (*buf)[i] == ',')
  29. sp++;
  30. if (!sp)
  31. return;
  32. for (i = l-1, j = i+sp; i >= 0; i--) {
  33. (*buf)[j--] = (*buf)[i];
  34. if ((*buf)[i] == '\\' || (*buf)[i] == ';' || (*buf)[i] == '=' || (*buf)[i] == ',')
  35. (*buf)[j--] = '\\';
  36. }
  37. }
  38. /*
  39. * Internal function to allocate memory for IMA measurements.
  40. */
  41. static void *dm_ima_alloc(size_t len, gfp_t flags, bool noio)
  42. {
  43. unsigned int noio_flag;
  44. void *ptr;
  45. if (noio)
  46. noio_flag = memalloc_noio_save();
  47. ptr = kzalloc(len, flags);
  48. if (noio)
  49. memalloc_noio_restore(noio_flag);
  50. return ptr;
  51. }
  52. /*
  53. * Internal function to allocate and copy name and uuid for IMA measurements.
  54. */
  55. static int dm_ima_alloc_and_copy_name_uuid(struct mapped_device *md, char **dev_name,
  56. char **dev_uuid, bool noio)
  57. {
  58. int r;
  59. *dev_name = dm_ima_alloc(DM_NAME_LEN*2, GFP_KERNEL, noio);
  60. if (!(*dev_name)) {
  61. r = -ENOMEM;
  62. goto error;
  63. }
  64. *dev_uuid = dm_ima_alloc(DM_UUID_LEN*2, GFP_KERNEL, noio);
  65. if (!(*dev_uuid)) {
  66. r = -ENOMEM;
  67. goto error;
  68. }
  69. r = dm_copy_name_and_uuid(md, *dev_name, *dev_uuid);
  70. if (r)
  71. goto error;
  72. fix_separator_chars(dev_name);
  73. fix_separator_chars(dev_uuid);
  74. return 0;
  75. error:
  76. kfree(*dev_name);
  77. kfree(*dev_uuid);
  78. *dev_name = NULL;
  79. *dev_uuid = NULL;
  80. return r;
  81. }
  82. /*
  83. * Internal function to allocate and copy device data for IMA measurements.
  84. */
  85. static int dm_ima_alloc_and_copy_device_data(struct mapped_device *md, char **device_data,
  86. unsigned int num_targets, bool noio)
  87. {
  88. char *dev_name = NULL, *dev_uuid = NULL;
  89. int r;
  90. r = dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio);
  91. if (r)
  92. return r;
  93. *device_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
  94. if (!(*device_data)) {
  95. r = -ENOMEM;
  96. goto error;
  97. }
  98. scnprintf(*device_data, DM_IMA_DEVICE_BUF_LEN,
  99. "name=%s,uuid=%s,major=%d,minor=%d,minor_count=%d,num_targets=%u;",
  100. dev_name, dev_uuid, md->disk->major, md->disk->first_minor,
  101. md->disk->minors, num_targets);
  102. error:
  103. kfree(dev_name);
  104. kfree(dev_uuid);
  105. return r;
  106. }
  107. /*
  108. * Internal wrapper function to call IMA to measure DM data.
  109. */
  110. static void dm_ima_measure_data(const char *event_name, const void *buf, size_t buf_len,
  111. bool noio)
  112. {
  113. unsigned int noio_flag;
  114. if (noio)
  115. noio_flag = memalloc_noio_save();
  116. ima_measure_critical_data(DM_NAME, event_name, buf, buf_len,
  117. false, NULL, 0);
  118. if (noio)
  119. memalloc_noio_restore(noio_flag);
  120. }
  121. /*
  122. * Internal function to allocate and copy current device capacity for IMA measurements.
  123. */
  124. static int dm_ima_alloc_and_copy_capacity_str(struct mapped_device *md, char **capacity_str,
  125. bool noio)
  126. {
  127. sector_t capacity;
  128. capacity = get_capacity(md->disk);
  129. *capacity_str = dm_ima_alloc(DM_IMA_DEVICE_CAPACITY_BUF_LEN, GFP_KERNEL, noio);
  130. if (!(*capacity_str))
  131. return -ENOMEM;
  132. scnprintf(*capacity_str, DM_IMA_DEVICE_BUF_LEN, "current_device_capacity=%llu;",
  133. capacity);
  134. return 0;
  135. }
  136. /*
  137. * Initialize/reset the dm ima related data structure variables.
  138. */
  139. void dm_ima_reset_data(struct mapped_device *md)
  140. {
  141. memset(&(md->ima), 0, sizeof(md->ima));
  142. md->ima.dm_version_str_len = strlen(DM_IMA_VERSION_STR);
  143. }
  144. /*
  145. * Build up the IMA data for each target, and finally measure.
  146. */
  147. void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_flags)
  148. {
  149. size_t device_data_buf_len, target_metadata_buf_len, target_data_buf_len, l = 0;
  150. char *target_metadata_buf = NULL, *target_data_buf = NULL, *digest_buf = NULL;
  151. char *ima_buf = NULL, *device_data_buf = NULL;
  152. int digest_size, last_target_measured = -1, r;
  153. status_type_t type = STATUSTYPE_IMA;
  154. size_t cur_total_buf_len = 0;
  155. unsigned int num_targets, i;
  156. SHASH_DESC_ON_STACK(shash, NULL);
  157. struct crypto_shash *tfm = NULL;
  158. u8 *digest = NULL;
  159. bool noio = false;
  160. /*
  161. * In below hash_alg_prefix_len assignment +1 is for the additional char (':'),
  162. * when prefixing the hash value with the hash algorithm name. e.g. sha256:<hash_value>.
  163. */
  164. const size_t hash_alg_prefix_len = strlen(DM_IMA_TABLE_HASH_ALG) + 1;
  165. char table_load_event_name[] = "dm_table_load";
  166. ima_buf = dm_ima_alloc(DM_IMA_MEASUREMENT_BUF_LEN, GFP_KERNEL, noio);
  167. if (!ima_buf)
  168. return;
  169. target_metadata_buf = dm_ima_alloc(DM_IMA_TARGET_METADATA_BUF_LEN, GFP_KERNEL, noio);
  170. if (!target_metadata_buf)
  171. goto error;
  172. target_data_buf = dm_ima_alloc(DM_IMA_TARGET_DATA_BUF_LEN, GFP_KERNEL, noio);
  173. if (!target_data_buf)
  174. goto error;
  175. num_targets = table->num_targets;
  176. if (dm_ima_alloc_and_copy_device_data(table->md, &device_data_buf, num_targets, noio))
  177. goto error;
  178. tfm = crypto_alloc_shash(DM_IMA_TABLE_HASH_ALG, 0, 0);
  179. if (IS_ERR(tfm))
  180. goto error;
  181. shash->tfm = tfm;
  182. digest_size = crypto_shash_digestsize(tfm);
  183. digest = dm_ima_alloc(digest_size, GFP_KERNEL, noio);
  184. if (!digest)
  185. goto error;
  186. r = crypto_shash_init(shash);
  187. if (r)
  188. goto error;
  189. memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
  190. l += table->md->ima.dm_version_str_len;
  191. device_data_buf_len = strlen(device_data_buf);
  192. memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
  193. l += device_data_buf_len;
  194. for (i = 0; i < num_targets; i++) {
  195. struct dm_target *ti = dm_table_get_target(table, i);
  196. last_target_measured = 0;
  197. /*
  198. * First retrieve the target metadata.
  199. */
  200. scnprintf(target_metadata_buf, DM_IMA_TARGET_METADATA_BUF_LEN,
  201. "target_index=%d,target_begin=%llu,target_len=%llu,",
  202. i, ti->begin, ti->len);
  203. target_metadata_buf_len = strlen(target_metadata_buf);
  204. /*
  205. * Then retrieve the actual target data.
  206. */
  207. if (ti->type->status)
  208. ti->type->status(ti, type, status_flags, target_data_buf,
  209. DM_IMA_TARGET_DATA_BUF_LEN);
  210. else
  211. target_data_buf[0] = '\0';
  212. target_data_buf_len = strlen(target_data_buf);
  213. /*
  214. * Check if the total data can fit into the IMA buffer.
  215. */
  216. cur_total_buf_len = l + target_metadata_buf_len + target_data_buf_len;
  217. /*
  218. * IMA measurements for DM targets are best-effort.
  219. * If the total data buffered so far, including the current target,
  220. * is too large to fit into DM_IMA_MEASUREMENT_BUF_LEN, measure what
  221. * we have in the current buffer, and continue measuring the remaining
  222. * targets by prefixing the device metadata again.
  223. */
  224. if (unlikely(cur_total_buf_len >= DM_IMA_MEASUREMENT_BUF_LEN)) {
  225. dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
  226. r = crypto_shash_update(shash, (const u8 *)ima_buf, l);
  227. if (r < 0)
  228. goto error;
  229. memset(ima_buf, 0, DM_IMA_MEASUREMENT_BUF_LEN);
  230. l = 0;
  231. /*
  232. * Each new "dm_table_load" entry in IMA log should have device data
  233. * prefix, so that multiple records from the same "dm_table_load" for
  234. * a given device can be linked together.
  235. */
  236. memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
  237. l += table->md->ima.dm_version_str_len;
  238. memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
  239. l += device_data_buf_len;
  240. /*
  241. * If this iteration of the for loop turns out to be the last target
  242. * in the table, dm_ima_measure_data("dm_table_load", ...) doesn't need
  243. * to be called again, just the hash needs to be finalized.
  244. * "last_target_measured" tracks this state.
  245. */
  246. last_target_measured = 1;
  247. }
  248. /*
  249. * Fill-in all the target metadata, so that multiple targets for the same
  250. * device can be linked together.
  251. */
  252. memcpy(ima_buf + l, target_metadata_buf, target_metadata_buf_len);
  253. l += target_metadata_buf_len;
  254. memcpy(ima_buf + l, target_data_buf, target_data_buf_len);
  255. l += target_data_buf_len;
  256. }
  257. if (!last_target_measured) {
  258. dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
  259. r = crypto_shash_update(shash, (const u8 *)ima_buf, l);
  260. if (r < 0)
  261. goto error;
  262. }
  263. /*
  264. * Finalize the table hash, and store it in table->md->ima.inactive_table.hash,
  265. * so that the table data can be verified against the future device state change
  266. * events, e.g. resume, rename, remove, table-clear etc.
  267. */
  268. r = crypto_shash_final(shash, digest);
  269. if (r < 0)
  270. goto error;
  271. digest_buf = dm_ima_alloc((digest_size*2) + hash_alg_prefix_len + 1, GFP_KERNEL, noio);
  272. if (!digest_buf)
  273. goto error;
  274. snprintf(digest_buf, hash_alg_prefix_len + 1, "%s:", DM_IMA_TABLE_HASH_ALG);
  275. for (i = 0; i < digest_size; i++)
  276. snprintf((digest_buf + hash_alg_prefix_len + (i*2)), 3, "%02x", digest[i]);
  277. if (table->md->ima.active_table.hash != table->md->ima.inactive_table.hash)
  278. kfree(table->md->ima.inactive_table.hash);
  279. table->md->ima.inactive_table.hash = digest_buf;
  280. table->md->ima.inactive_table.hash_len = strlen(digest_buf);
  281. table->md->ima.inactive_table.num_targets = num_targets;
  282. if (table->md->ima.active_table.device_metadata !=
  283. table->md->ima.inactive_table.device_metadata)
  284. kfree(table->md->ima.inactive_table.device_metadata);
  285. table->md->ima.inactive_table.device_metadata = device_data_buf;
  286. table->md->ima.inactive_table.device_metadata_len = device_data_buf_len;
  287. goto exit;
  288. error:
  289. kfree(digest_buf);
  290. kfree(device_data_buf);
  291. exit:
  292. kfree(digest);
  293. if (tfm)
  294. crypto_free_shash(tfm);
  295. kfree(ima_buf);
  296. kfree(target_metadata_buf);
  297. kfree(target_data_buf);
  298. }
  299. /*
  300. * Measure IMA data on device resume.
  301. */
  302. void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
  303. {
  304. char *device_table_data, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
  305. char active[] = "active_table_hash=";
  306. unsigned int active_len = strlen(active), capacity_len = 0;
  307. unsigned int l = 0;
  308. bool noio = true;
  309. bool nodata = true;
  310. int r;
  311. device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
  312. if (!device_table_data)
  313. return;
  314. r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
  315. if (r)
  316. goto error;
  317. memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
  318. l += md->ima.dm_version_str_len;
  319. if (swap) {
  320. if (md->ima.active_table.hash != md->ima.inactive_table.hash)
  321. kfree(md->ima.active_table.hash);
  322. md->ima.active_table.hash = NULL;
  323. md->ima.active_table.hash_len = 0;
  324. if (md->ima.active_table.device_metadata !=
  325. md->ima.inactive_table.device_metadata)
  326. kfree(md->ima.active_table.device_metadata);
  327. md->ima.active_table.device_metadata = NULL;
  328. md->ima.active_table.device_metadata_len = 0;
  329. md->ima.active_table.num_targets = 0;
  330. if (md->ima.inactive_table.hash) {
  331. md->ima.active_table.hash = md->ima.inactive_table.hash;
  332. md->ima.active_table.hash_len = md->ima.inactive_table.hash_len;
  333. md->ima.inactive_table.hash = NULL;
  334. md->ima.inactive_table.hash_len = 0;
  335. }
  336. if (md->ima.inactive_table.device_metadata) {
  337. md->ima.active_table.device_metadata =
  338. md->ima.inactive_table.device_metadata;
  339. md->ima.active_table.device_metadata_len =
  340. md->ima.inactive_table.device_metadata_len;
  341. md->ima.active_table.num_targets = md->ima.inactive_table.num_targets;
  342. md->ima.inactive_table.device_metadata = NULL;
  343. md->ima.inactive_table.device_metadata_len = 0;
  344. md->ima.inactive_table.num_targets = 0;
  345. }
  346. }
  347. if (md->ima.active_table.device_metadata) {
  348. memcpy(device_table_data + l, md->ima.active_table.device_metadata,
  349. md->ima.active_table.device_metadata_len);
  350. l += md->ima.active_table.device_metadata_len;
  351. nodata = false;
  352. }
  353. if (md->ima.active_table.hash) {
  354. memcpy(device_table_data + l, active, active_len);
  355. l += active_len;
  356. memcpy(device_table_data + l, md->ima.active_table.hash,
  357. md->ima.active_table.hash_len);
  358. l += md->ima.active_table.hash_len;
  359. memcpy(device_table_data + l, ";", 1);
  360. l++;
  361. nodata = false;
  362. }
  363. if (nodata) {
  364. r = dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio);
  365. if (r)
  366. goto error;
  367. scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
  368. "%sname=%s,uuid=%s;device_resume=no_data;",
  369. DM_IMA_VERSION_STR, dev_name, dev_uuid);
  370. l = strlen(device_table_data);
  371. }
  372. capacity_len = strlen(capacity_str);
  373. memcpy(device_table_data + l, capacity_str, capacity_len);
  374. l += capacity_len;
  375. dm_ima_measure_data("dm_device_resume", device_table_data, l, noio);
  376. kfree(dev_name);
  377. kfree(dev_uuid);
  378. error:
  379. kfree(capacity_str);
  380. kfree(device_table_data);
  381. }
  382. /*
  383. * Measure IMA data on remove.
  384. */
  385. void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
  386. {
  387. char *device_table_data, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
  388. char active_table_str[] = "active_table_hash=";
  389. char inactive_table_str[] = "inactive_table_hash=";
  390. char device_active_str[] = "device_active_metadata=";
  391. char device_inactive_str[] = "device_inactive_metadata=";
  392. char remove_all_str[] = "remove_all=";
  393. unsigned int active_table_len = strlen(active_table_str);
  394. unsigned int inactive_table_len = strlen(inactive_table_str);
  395. unsigned int device_active_len = strlen(device_active_str);
  396. unsigned int device_inactive_len = strlen(device_inactive_str);
  397. unsigned int remove_all_len = strlen(remove_all_str);
  398. unsigned int capacity_len = 0;
  399. unsigned int l = 0;
  400. bool noio = true;
  401. bool nodata = true;
  402. int r;
  403. device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN*2, GFP_KERNEL, noio);
  404. if (!device_table_data)
  405. goto exit;
  406. r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
  407. if (r) {
  408. kfree(device_table_data);
  409. goto exit;
  410. }
  411. memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
  412. l += md->ima.dm_version_str_len;
  413. if (md->ima.active_table.device_metadata) {
  414. memcpy(device_table_data + l, device_active_str, device_active_len);
  415. l += device_active_len;
  416. memcpy(device_table_data + l, md->ima.active_table.device_metadata,
  417. md->ima.active_table.device_metadata_len);
  418. l += md->ima.active_table.device_metadata_len;
  419. nodata = false;
  420. }
  421. if (md->ima.inactive_table.device_metadata) {
  422. memcpy(device_table_data + l, device_inactive_str, device_inactive_len);
  423. l += device_inactive_len;
  424. memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
  425. md->ima.inactive_table.device_metadata_len);
  426. l += md->ima.inactive_table.device_metadata_len;
  427. nodata = false;
  428. }
  429. if (md->ima.active_table.hash) {
  430. memcpy(device_table_data + l, active_table_str, active_table_len);
  431. l += active_table_len;
  432. memcpy(device_table_data + l, md->ima.active_table.hash,
  433. md->ima.active_table.hash_len);
  434. l += md->ima.active_table.hash_len;
  435. memcpy(device_table_data + l, ",", 1);
  436. l++;
  437. nodata = false;
  438. }
  439. if (md->ima.inactive_table.hash) {
  440. memcpy(device_table_data + l, inactive_table_str, inactive_table_len);
  441. l += inactive_table_len;
  442. memcpy(device_table_data + l, md->ima.inactive_table.hash,
  443. md->ima.inactive_table.hash_len);
  444. l += md->ima.inactive_table.hash_len;
  445. memcpy(device_table_data + l, ",", 1);
  446. l++;
  447. nodata = false;
  448. }
  449. /*
  450. * In case both active and inactive tables, and corresponding
  451. * device metadata is cleared/missing - record the name and uuid
  452. * in IMA measurements.
  453. */
  454. if (nodata) {
  455. if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
  456. goto error;
  457. scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
  458. "%sname=%s,uuid=%s;device_remove=no_data;",
  459. DM_IMA_VERSION_STR, dev_name, dev_uuid);
  460. l = strlen(device_table_data);
  461. }
  462. memcpy(device_table_data + l, remove_all_str, remove_all_len);
  463. l += remove_all_len;
  464. memcpy(device_table_data + l, remove_all ? "y;" : "n;", 2);
  465. l += 2;
  466. capacity_len = strlen(capacity_str);
  467. memcpy(device_table_data + l, capacity_str, capacity_len);
  468. l += capacity_len;
  469. dm_ima_measure_data("dm_device_remove", device_table_data, l, noio);
  470. error:
  471. kfree(device_table_data);
  472. kfree(capacity_str);
  473. exit:
  474. kfree(md->ima.active_table.device_metadata);
  475. if (md->ima.active_table.device_metadata !=
  476. md->ima.inactive_table.device_metadata)
  477. kfree(md->ima.inactive_table.device_metadata);
  478. kfree(md->ima.active_table.hash);
  479. if (md->ima.active_table.hash != md->ima.inactive_table.hash)
  480. kfree(md->ima.inactive_table.hash);
  481. dm_ima_reset_data(md);
  482. kfree(dev_name);
  483. kfree(dev_uuid);
  484. }
  485. /*
  486. * Measure ima data on table clear.
  487. */
  488. void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
  489. {
  490. unsigned int l = 0, capacity_len = 0;
  491. char *device_table_data = NULL, *dev_name = NULL, *dev_uuid = NULL, *capacity_str = NULL;
  492. char inactive_str[] = "inactive_table_hash=";
  493. unsigned int inactive_len = strlen(inactive_str);
  494. bool noio = true;
  495. bool nodata = true;
  496. int r;
  497. device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
  498. if (!device_table_data)
  499. return;
  500. r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
  501. if (r)
  502. goto error1;
  503. memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
  504. l += md->ima.dm_version_str_len;
  505. if (md->ima.inactive_table.device_metadata_len &&
  506. md->ima.inactive_table.hash_len) {
  507. memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
  508. md->ima.inactive_table.device_metadata_len);
  509. l += md->ima.inactive_table.device_metadata_len;
  510. memcpy(device_table_data + l, inactive_str, inactive_len);
  511. l += inactive_len;
  512. memcpy(device_table_data + l, md->ima.inactive_table.hash,
  513. md->ima.inactive_table.hash_len);
  514. l += md->ima.inactive_table.hash_len;
  515. memcpy(device_table_data + l, ";", 1);
  516. l++;
  517. nodata = false;
  518. }
  519. if (nodata) {
  520. if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
  521. goto error2;
  522. scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
  523. "%sname=%s,uuid=%s;table_clear=no_data;",
  524. DM_IMA_VERSION_STR, dev_name, dev_uuid);
  525. l = strlen(device_table_data);
  526. }
  527. capacity_len = strlen(capacity_str);
  528. memcpy(device_table_data + l, capacity_str, capacity_len);
  529. l += capacity_len;
  530. dm_ima_measure_data("dm_table_clear", device_table_data, l, noio);
  531. if (new_map) {
  532. if (md->ima.inactive_table.hash &&
  533. md->ima.inactive_table.hash != md->ima.active_table.hash)
  534. kfree(md->ima.inactive_table.hash);
  535. md->ima.inactive_table.hash = NULL;
  536. md->ima.inactive_table.hash_len = 0;
  537. if (md->ima.inactive_table.device_metadata &&
  538. md->ima.inactive_table.device_metadata != md->ima.active_table.device_metadata)
  539. kfree(md->ima.inactive_table.device_metadata);
  540. md->ima.inactive_table.device_metadata = NULL;
  541. md->ima.inactive_table.device_metadata_len = 0;
  542. md->ima.inactive_table.num_targets = 0;
  543. if (md->ima.active_table.hash) {
  544. md->ima.inactive_table.hash = md->ima.active_table.hash;
  545. md->ima.inactive_table.hash_len = md->ima.active_table.hash_len;
  546. }
  547. if (md->ima.active_table.device_metadata) {
  548. md->ima.inactive_table.device_metadata =
  549. md->ima.active_table.device_metadata;
  550. md->ima.inactive_table.device_metadata_len =
  551. md->ima.active_table.device_metadata_len;
  552. md->ima.inactive_table.num_targets =
  553. md->ima.active_table.num_targets;
  554. }
  555. }
  556. kfree(dev_name);
  557. kfree(dev_uuid);
  558. error2:
  559. kfree(capacity_str);
  560. error1:
  561. kfree(device_table_data);
  562. }
  563. /*
  564. * Measure IMA data on device rename.
  565. */
  566. void dm_ima_measure_on_device_rename(struct mapped_device *md)
  567. {
  568. char *old_device_data = NULL, *new_device_data = NULL, *combined_device_data = NULL;
  569. char *new_dev_name = NULL, *new_dev_uuid = NULL, *capacity_str = NULL;
  570. bool noio = true;
  571. int r;
  572. if (dm_ima_alloc_and_copy_device_data(md, &new_device_data,
  573. md->ima.active_table.num_targets, noio))
  574. return;
  575. if (dm_ima_alloc_and_copy_name_uuid(md, &new_dev_name, &new_dev_uuid, noio))
  576. goto error;
  577. combined_device_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN * 2, GFP_KERNEL, noio);
  578. if (!combined_device_data)
  579. goto error;
  580. r = dm_ima_alloc_and_copy_capacity_str(md, &capacity_str, noio);
  581. if (r)
  582. goto error;
  583. old_device_data = md->ima.active_table.device_metadata;
  584. md->ima.active_table.device_metadata = new_device_data;
  585. md->ima.active_table.device_metadata_len = strlen(new_device_data);
  586. scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2,
  587. "%s%snew_name=%s,new_uuid=%s;%s", DM_IMA_VERSION_STR, old_device_data,
  588. new_dev_name, new_dev_uuid, capacity_str);
  589. dm_ima_measure_data("dm_device_rename", combined_device_data, strlen(combined_device_data),
  590. noio);
  591. goto exit;
  592. error:
  593. kfree(new_device_data);
  594. exit:
  595. kfree(capacity_str);
  596. kfree(combined_device_data);
  597. kfree(old_device_data);
  598. kfree(new_dev_name);
  599. kfree(new_dev_uuid);
  600. }