diff options
author | Peter Jones <pjones@redhat.com> | 2016-02-08 14:48:15 -0500 |
---|---|---|
committer | Matt Fleming <matt@codeblueprint.co.uk> | 2016-02-10 11:25:52 -0500 |
commit | ed8b0de5a33d2a2557dce7f9429dca8cb5bc5879 (patch) | |
tree | 1dcd2e49cc432ae312677ec47453ec3abc18f1d2 /fs/efivarfs/super.c | |
parent | 8282f5d9c17fe15a9e658c06e3f343efae1a2a2f (diff) |
efi: Make efivarfs entries immutable by default
"rm -rf" is bricking some peoples' laptops because of variables being
used to store non-reinitializable firmware driver data that's required
to POST the hardware.
These are 100% bugs, and they need to be fixed, but in the mean time it
shouldn't be easy to *accidentally* brick machines.
We have to have delete working, and picking which variables do and don't
work for deletion is quite intractable, so instead make everything
immutable by default (except for a whitelist), and make tools that
aren't quite so broad-spectrum unset the immutable flag.
Signed-off-by: Peter Jones <pjones@redhat.com>
Tested-by: Lee, Chun-Yi <jlee@suse.com>
Acked-by: Matthew Garrett <mjg59@coreos.com>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Diffstat (limited to 'fs/efivarfs/super.c')
-rw-r--r-- | fs/efivarfs/super.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index 8651ac28ec0d..dd029d13ea61 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c | |||
@@ -120,6 +120,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, | |||
120 | char *name; | 120 | char *name; |
121 | int len; | 121 | int len; |
122 | int err = -ENOMEM; | 122 | int err = -ENOMEM; |
123 | bool is_removable = false; | ||
123 | 124 | ||
124 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 125 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
125 | if (!entry) | 126 | if (!entry) |
@@ -137,13 +138,17 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, | |||
137 | 138 | ||
138 | ucs2_as_utf8(name, entry->var.VariableName, len); | 139 | ucs2_as_utf8(name, entry->var.VariableName, len); |
139 | 140 | ||
141 | if (efivar_variable_is_removable(entry->var.VendorGuid, name, len)) | ||
142 | is_removable = true; | ||
143 | |||
140 | name[len] = '-'; | 144 | name[len] = '-'; |
141 | 145 | ||
142 | efi_guid_to_str(&entry->var.VendorGuid, name + len + 1); | 146 | efi_guid_to_str(&entry->var.VendorGuid, name + len + 1); |
143 | 147 | ||
144 | name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; | 148 | name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; |
145 | 149 | ||
146 | inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0); | 150 | inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0, |
151 | is_removable); | ||
147 | if (!inode) | 152 | if (!inode) |
148 | goto fail_name; | 153 | goto fail_name; |
149 | 154 | ||
@@ -199,7 +204,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
199 | sb->s_d_op = &efivarfs_d_ops; | 204 | sb->s_d_op = &efivarfs_d_ops; |
200 | sb->s_time_gran = 1; | 205 | sb->s_time_gran = 1; |
201 | 206 | ||
202 | inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); | 207 | inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true); |
203 | if (!inode) | 208 | if (!inode) |
204 | return -ENOMEM; | 209 | return -ENOMEM; |
205 | inode->i_op = &efivarfs_dir_inode_operations; | 210 | inode->i_op = &efivarfs_dir_inode_operations; |