diff options
| author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-09-07 08:36:45 -0400 |
|---|---|---|
| committer | Richard Weinberger <richard@nod.at> | 2018-10-23 07:49:01 -0400 |
| commit | d8a22773a12c6d78ee758c9e530f3a488bb7cb29 (patch) | |
| tree | 0c294033e71684c115bd30677155c3c1533751e3 | |
| parent | 1e76592f2c3208ac635c2758aa8326d82fa64a72 (diff) | |
ubifs: Enable authentication support
With the preparations all being done this patch now enables authentication
support for UBIFS. Authentication is enabled when the newly introduced
auth_key and auth_hash_name mount options are passed. auth_key provides
the key which is used for authentication whereas auth_hash_name provides
the hashing algorithm used for this FS. Passing these options make
authentication mandatory and only UBIFS images that can be authenticated
with the given key are allowed.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Richard Weinberger <richard@nod.at>
| -rw-r--r-- | Documentation/filesystems/ubifs.txt | 7 | ||||
| -rw-r--r-- | fs/ubifs/Kconfig | 10 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 36 |
3 files changed, 52 insertions, 1 deletions
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index a0a61d2f389f..acc80442a3bb 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt | |||
| @@ -91,6 +91,13 @@ chk_data_crc do not skip checking CRCs on data nodes | |||
| 91 | compr=none override default compressor and set it to "none" | 91 | compr=none override default compressor and set it to "none" |
| 92 | compr=lzo override default compressor and set it to "lzo" | 92 | compr=lzo override default compressor and set it to "lzo" |
| 93 | compr=zlib override default compressor and set it to "zlib" | 93 | compr=zlib override default compressor and set it to "zlib" |
| 94 | auth_key= specify the key used for authenticating the filesystem. | ||
| 95 | Passing this option makes authentication mandatory. | ||
| 96 | The passed key must be present in the kernel keyring | ||
| 97 | and must be of type 'logon' | ||
| 98 | auth_hash_name= The hash algorithm used for authentication. Used for | ||
| 99 | both hashing and for creating HMACs. Typical values | ||
| 100 | include "sha256" or "sha512" | ||
| 94 | 101 | ||
| 95 | 102 | ||
| 96 | Quick usage instructions | 103 | Quick usage instructions |
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index 853c77579b4e..529856fbccd0 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig | |||
| @@ -86,3 +86,13 @@ config UBIFS_FS_SECURITY | |||
| 86 | the extended attribute support in advance. | 86 | the extended attribute support in advance. |
| 87 | 87 | ||
| 88 | If you are not using a security module, say N. | 88 | If you are not using a security module, say N. |
| 89 | |||
| 90 | config UBIFS_FS_AUTHENTICATION | ||
| 91 | bool "UBIFS authentication support" | ||
| 92 | select CRYPTO_HMAC | ||
| 93 | help | ||
| 94 | Enable authentication support for UBIFS. This feature offers protection | ||
| 95 | against offline changes for both data and metadata of the filesystem. | ||
| 96 | If you say yes here you should also select a hashing algorithm such as | ||
| 97 | sha256, these are not selected automatically since there are many | ||
| 98 | different options. | ||
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index e2964ce81dee..1fac1133dadd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -579,7 +579,9 @@ static int init_constants_early(struct ubifs_info *c) | |||
| 579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; | 579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; |
| 580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; | 580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; |
| 581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; | 581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; |
| 582 | c->ranges[UBIFS_AUTH_NODE].len = UBIFS_AUTH_NODE_SZ; | 582 | c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; |
| 583 | c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + | ||
| 584 | UBIFS_MAX_HMAC_LEN; | ||
| 583 | 585 | ||
| 584 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; | 586 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; |
| 585 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; | 587 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; |
| @@ -935,6 +937,8 @@ static int check_volume_empty(struct ubifs_info *c) | |||
| 935 | * Opt_no_chk_data_crc: do not check CRCs when reading data nodes | 937 | * Opt_no_chk_data_crc: do not check CRCs when reading data nodes |
| 936 | * Opt_override_compr: override default compressor | 938 | * Opt_override_compr: override default compressor |
| 937 | * Opt_assert: set ubifs_assert() action | 939 | * Opt_assert: set ubifs_assert() action |
| 940 | * Opt_auth_key: The key name used for authentication | ||
| 941 | * Opt_auth_hash_name: The hash type used for authentication | ||
| 938 | * Opt_err: just end of array marker | 942 | * Opt_err: just end of array marker |
| 939 | */ | 943 | */ |
| 940 | enum { | 944 | enum { |
| @@ -946,6 +950,8 @@ enum { | |||
| 946 | Opt_no_chk_data_crc, | 950 | Opt_no_chk_data_crc, |
| 947 | Opt_override_compr, | 951 | Opt_override_compr, |
| 948 | Opt_assert, | 952 | Opt_assert, |
| 953 | Opt_auth_key, | ||
| 954 | Opt_auth_hash_name, | ||
| 949 | Opt_ignore, | 955 | Opt_ignore, |
| 950 | Opt_err, | 956 | Opt_err, |
| 951 | }; | 957 | }; |
| @@ -958,6 +964,8 @@ static const match_table_t tokens = { | |||
| 958 | {Opt_chk_data_crc, "chk_data_crc"}, | 964 | {Opt_chk_data_crc, "chk_data_crc"}, |
| 959 | {Opt_no_chk_data_crc, "no_chk_data_crc"}, | 965 | {Opt_no_chk_data_crc, "no_chk_data_crc"}, |
| 960 | {Opt_override_compr, "compr=%s"}, | 966 | {Opt_override_compr, "compr=%s"}, |
| 967 | {Opt_auth_key, "auth_key=%s"}, | ||
| 968 | {Opt_auth_hash_name, "auth_hash_name=%s"}, | ||
| 961 | {Opt_ignore, "ubi=%s"}, | 969 | {Opt_ignore, "ubi=%s"}, |
| 962 | {Opt_ignore, "vol=%s"}, | 970 | {Opt_ignore, "vol=%s"}, |
| 963 | {Opt_assert, "assert=%s"}, | 971 | {Opt_assert, "assert=%s"}, |
| @@ -1081,6 +1089,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
| 1081 | kfree(act); | 1089 | kfree(act); |
| 1082 | break; | 1090 | break; |
| 1083 | } | 1091 | } |
| 1092 | case Opt_auth_key: | ||
| 1093 | c->auth_key_name = kstrdup(args[0].from, GFP_KERNEL); | ||
| 1094 | if (!c->auth_key_name) | ||
| 1095 | return -ENOMEM; | ||
| 1096 | break; | ||
| 1097 | case Opt_auth_hash_name: | ||
| 1098 | c->auth_hash_name = kstrdup(args[0].from, GFP_KERNEL); | ||
| 1099 | if (!c->auth_hash_name) | ||
| 1100 | return -ENOMEM; | ||
| 1101 | break; | ||
| 1084 | case Opt_ignore: | 1102 | case Opt_ignore: |
| 1085 | break; | 1103 | break; |
| 1086 | default: | 1104 | default: |
| @@ -1260,6 +1278,19 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1260 | 1278 | ||
| 1261 | c->mounting = 1; | 1279 | c->mounting = 1; |
| 1262 | 1280 | ||
| 1281 | if (c->auth_key_name) { | ||
| 1282 | if (IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) { | ||
| 1283 | err = ubifs_init_authentication(c); | ||
| 1284 | if (err) | ||
| 1285 | goto out_free; | ||
| 1286 | } else { | ||
| 1287 | ubifs_err(c, "auth_key_name, but UBIFS is built without" | ||
| 1288 | " authentication support"); | ||
| 1289 | err = -EINVAL; | ||
| 1290 | goto out_free; | ||
| 1291 | } | ||
| 1292 | } | ||
| 1293 | |||
| 1263 | err = ubifs_read_superblock(c); | 1294 | err = ubifs_read_superblock(c); |
| 1264 | if (err) | 1295 | if (err) |
| 1265 | goto out_free; | 1296 | goto out_free; |
| @@ -1577,7 +1608,10 @@ static void ubifs_umount(struct ubifs_info *c) | |||
| 1577 | free_wbufs(c); | 1608 | free_wbufs(c); |
| 1578 | free_orphans(c); | 1609 | free_orphans(c); |
| 1579 | ubifs_lpt_free(c, 0); | 1610 | ubifs_lpt_free(c, 0); |
| 1611 | ubifs_exit_authentication(c); | ||
| 1580 | 1612 | ||
| 1613 | kfree(c->auth_key_name); | ||
| 1614 | kfree(c->auth_hash_name); | ||
| 1581 | kfree(c->cbuf); | 1615 | kfree(c->cbuf); |
| 1582 | kfree(c->rcvrd_mst_node); | 1616 | kfree(c->rcvrd_mst_node); |
| 1583 | kfree(c->mst_node); | 1617 | kfree(c->mst_node); |
