mirror of
https://codeberg.org/libreboot/grub.git
synced 2025-07-06 17:02:11 +00:00
Compare commits
326 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a68a7dece4 | ||
|
de80acf368 | ||
|
249db11d8f | ||
|
f3b339af11 | ||
|
c2b2e0dcf5 | ||
|
de4e8e2aa6 | ||
|
8c8f966643 | ||
|
8ebf155af3 | ||
|
2f2ed28d5a | ||
|
2539ede82a | ||
|
8c2d4e64ff | ||
|
ba8eadde6b | ||
|
409e72cedf | ||
|
5eca564b19 | ||
|
ac1512b872 | ||
|
db506b3b83 | ||
|
bba7dd7363 | ||
|
91cb7ff6bb | ||
|
451e227e53 | ||
|
11caacdb22 | ||
|
ce23919cac | ||
|
e3b15bafd1 | ||
|
40e261b89b | ||
|
86e8f2c4b0 | ||
|
438f055819 | ||
|
20e6d0c4a4 | ||
|
b71bc0f8b4 | ||
|
272ff81cb2 | ||
|
8c95307a0b | ||
|
06914b6141 | ||
|
0e1762c8a0 | ||
|
be303f8c18 | ||
|
34bd00ee26 | ||
|
ca2a91f43b | ||
|
73d1c959ea | ||
|
dbc0eb5bd1 | ||
|
301b4ef25a | ||
|
23ec4535f4 | ||
|
10d778c4b4 | ||
|
7a584fbde0 | ||
|
ed691c0e0e | ||
|
c448f511e7 | ||
|
4abac0ad5a | ||
|
a4da71dafe | ||
|
223fcf8084 | ||
|
6504a8d4bd | ||
|
8fef533cf6 | ||
|
1fe0948558 | ||
|
6252eb97ca | ||
|
9d4b382aa0 | ||
|
2043b6899b | ||
|
9f66a4719b | ||
|
b7d89e6671 | ||
|
5934bf51cb | ||
|
cd9cb944d9 | ||
|
fa69deac56 | ||
|
75c480885a | ||
|
041164d00e | ||
|
46c9f3a8da | ||
|
617dab9e47 | ||
|
204a6ddfb3 | ||
|
6b64f297e5 | ||
|
f94d257e8c | ||
|
81146fb623 | ||
|
1d00594475 | ||
|
f3f1fcecdc | ||
|
aae2ea619e | ||
|
3b25e494d4 | ||
|
fee6081ec7 | ||
|
b66c6f9182 | ||
|
1d59f39b5f | ||
|
e0116f3bd5 | ||
|
e6e2b73db8 | ||
|
32b02bb92e | ||
|
c188ca5d5e | ||
|
50320c093a | ||
|
bb6d3199b3 | ||
|
3fd163e453 | ||
|
ff7f553071 | ||
|
a16b4304a2 | ||
|
9a37d61145 | ||
|
6c14b87d6f | ||
|
d34b9120e7 | ||
|
90848a1f7c | ||
|
488ac8bda9 | ||
|
096bf59e4c | ||
|
90288fc48d | ||
|
6337d84afa | ||
|
cbfb031b14 | ||
|
112d2069cf | ||
|
da9740cd52 | ||
|
1acf11fe4c | ||
|
6a168afd32 | ||
|
be0ae9583e | ||
|
ee27f07a65 | ||
|
cb639acea0 | ||
|
696e35b7ff | ||
|
187338f1ac | ||
|
ff173a1c0c | ||
|
fbcc388917 | ||
|
56ccc5ed56 | ||
|
01f064064c | ||
|
3f440b5a53 | ||
|
f209887381 | ||
|
1ed2628b56 | ||
|
348cd416a3 | ||
|
c730eddd2a | ||
|
f0a08324d0 | ||
|
7161e2437d | ||
|
11b9c2dd0d | ||
|
224aefd057 | ||
|
531750f7bf | ||
|
f2a1f66e72 | ||
|
13f005ed83 | ||
|
4dc6166571 | ||
|
490a6ab71c | ||
|
a8d6b06331 | ||
|
8e6e87e792 | ||
|
5b36a5210e | ||
|
9907d9c272 | ||
|
f8795cde21 | ||
|
66733f7c7d | ||
|
d13b6e8ebd | ||
|
e3c578a56f | ||
|
1c06ec9005 | ||
|
dee2c14fd6 | ||
|
4beeff8a31 | ||
|
dd6a4c8d10 | ||
|
13065f69da | ||
|
7f38e32c7e | ||
|
88e491a0f7 | ||
|
cde9f7f338 | ||
|
84bc0a9a68 | ||
|
6608163b08 | ||
|
fbaddcca54 | ||
|
33bd6b5ac5 | ||
|
d8151f9833 | ||
|
c407724dad | ||
|
c4bc55da28 | ||
|
26db660503 | ||
|
5f31164aed | ||
|
340e4d058f | ||
|
34824806ac | ||
|
c68b7d2362 | ||
|
dad8f50297 | ||
|
b970a5ed96 | ||
|
09bd6eb58b | ||
|
7580addfc8 | ||
|
9c16197734 | ||
|
2123c5bca7 | ||
|
0bf56bce47 | ||
|
05be856a8c | ||
|
98ad84328d | ||
|
d72208423d | ||
|
500e5fdd82 | ||
|
2c34af908e | ||
|
0707accab1 | ||
|
5eef881528 | ||
|
aa8b4d7fac | ||
|
a1dd8e59da | ||
|
d8a937ccae | ||
|
8a7103fddf | ||
|
18212f0648 | ||
|
67f70f70a3 | ||
|
13febd78db | ||
|
16f196874f | ||
|
a791068729 | ||
|
d1d6b7ea58 | ||
|
6ccc77b59d | ||
|
067b6d225d | ||
|
048777bc29 | ||
|
237a71184a | ||
|
aff2631878 | ||
|
7e2f750f0a | ||
|
edd995a26e | ||
|
bd999310fe | ||
|
ab09fd0531 | ||
|
66175696f3 | ||
|
1443833a95 | ||
|
965db59708 | ||
|
f7c070a2e2 | ||
|
563436258c | ||
|
0087bc6902 | ||
|
2c8ac08c99 | ||
|
417547c104 | ||
|
c1a291b01f | ||
|
ea703528a8 | ||
|
6811f6f09d | ||
|
ff14b89bda | ||
|
72092a8641 | ||
|
8c0b5f2003 | ||
|
7344b3c7ce | ||
|
29d1bd2a96 | ||
|
99ee68a014 | ||
|
3770a69050 | ||
|
f898440cc1 | ||
|
76a2bcb997 | ||
|
135e0bc886 | ||
|
b35480b48e | ||
|
6abf8af3c5 | ||
|
fba3a474e0 | ||
|
550ada7d67 | ||
|
5f6a2fd513 | ||
|
ad0c52784a | ||
|
48e230c317 | ||
|
35c9904df4 | ||
|
63a78f4b4d | ||
|
2ad159d9b3 | ||
|
5d260302da | ||
|
3d60732f9f | ||
|
99cda67889 | ||
|
504058e82a | ||
|
8a0fedef21 | ||
|
66cf4cb144 | ||
|
0d0913fc61 | ||
|
2e93a8e4bd | ||
|
b7568e3358 | ||
|
d60a04baef | ||
|
54e0e19a29 | ||
|
0ad1d4ba86 | ||
|
4160ca9839 | ||
|
8f56e5e5cf | ||
|
d86df91cbe | ||
|
32fdfe6008 | ||
|
fa498af7b9 | ||
|
9a26abbc36 | ||
|
c85c2b9f5f | ||
|
4f6c460917 | ||
|
792132c72a | ||
|
1763d83f54 | ||
|
097fd9d9a1 | ||
|
f48e6af117 | ||
|
dd743ba42d | ||
|
9a9082b501 | ||
|
f97d4618a5 | ||
|
f26b39860d | ||
|
337cb24862 | ||
|
31de991dee | ||
|
f5bb766e68 | ||
|
94649c0267 | ||
|
09ca66673a | ||
|
9fb80dd57e | ||
|
6e2fe134ef | ||
|
2b79d550f3 | ||
|
246c82cdae | ||
|
616adeb80b | ||
|
95a7bfef5d | ||
|
1b1061409d | ||
|
929fafdf5e | ||
|
d96cfd7bf8 | ||
|
86ec48882b | ||
|
3808b1a9bd | ||
|
e5f047be05 | ||
|
c5ae124e11 | ||
|
9c34d56c2d | ||
|
92bed41bf8 | ||
|
33cb8aecdd | ||
|
77cd623dee | ||
|
95145eea5e | ||
|
d333e8bb37 | ||
|
34b7f37212 | ||
|
ed06516738 | ||
|
648f2d16c0 | ||
|
f0710d2d8f | ||
|
e61157bbd2 | ||
|
5313fa8394 | ||
|
33b94f2a9b | ||
|
ab1e6fc044 | ||
|
9537f4403d | ||
|
b53ec06a1d | ||
|
ab9fe80300 | ||
|
0cfec355d0 | ||
|
f171122f03 | ||
|
828717833f | ||
|
9a2134a70f | ||
|
f96df6fe9f | ||
|
55d35d6283 | ||
|
61f1d0a612 | ||
|
dc0a3a27d6 | ||
|
b990df0bef | ||
|
d41c64811d | ||
|
c1ee4da6a9 | ||
|
c22e052fe2 | ||
|
d2fc9dfcd1 | ||
|
88a7e64c2c | ||
|
b8d29f1146 | ||
|
13b315c0a5 | ||
|
8abec8e153 | ||
|
d35ff22516 | ||
|
86df79275d | ||
|
0b4d01794a | ||
|
fa36f63760 | ||
|
c464f1ec34 | ||
|
2ffc14ba95 | ||
|
c6ac491204 | ||
|
5e8989e4ed | ||
|
c806e4dc88 | ||
|
243682baaa | ||
|
bb65d81fe3 | ||
|
56e58828cf | ||
|
9d603061aa | ||
|
1ba39de62f | ||
|
d291449ba3 | ||
|
6cc2e4481b | ||
|
f456add5f4 | ||
|
386b59ddb4 | ||
|
99b4c0c384 | ||
|
b272ed230e | ||
|
6744840b17 | ||
|
8719cc2040 | ||
|
0876fdf215 | ||
|
28c4405208 | ||
|
52e039e00b | ||
|
aa80270154 | ||
|
39c927df66 | ||
|
68dd65cfda | ||
|
04d2a50f31 | ||
|
4380c2d8ad | ||
|
9e1b18fc17 | ||
|
a8c0504515 | ||
|
d89a2a6e57 | ||
|
db0d19dc5f | ||
|
c8bf758757 | ||
|
5a311d029f | ||
|
b835601c76 | ||
|
8961305b4e |
291 changed files with 31269 additions and 1619 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -11,7 +11,6 @@
|
||||||
*.img
|
*.img
|
||||||
*.log
|
*.log
|
||||||
*.lst
|
*.lst
|
||||||
!/grub-core/extra_deps.lst
|
|
||||||
*.marker
|
*.marker
|
||||||
*.mod
|
*.mod
|
||||||
*.o
|
*.o
|
||||||
|
@ -105,6 +104,7 @@ widthspec.bin
|
||||||
/docs/version-dev.texi
|
/docs/version-dev.texi
|
||||||
/docs/version.texi
|
/docs/version.texi
|
||||||
/ehci_test
|
/ehci_test
|
||||||
|
/erofs_test
|
||||||
/example_grub_script_test
|
/example_grub_script_test
|
||||||
/example_scripted_test
|
/example_scripted_test
|
||||||
/example_unit_test
|
/example_unit_test
|
||||||
|
@ -141,10 +141,12 @@ widthspec.bin
|
||||||
/grub-core/kernel.img.bin
|
/grub-core/kernel.img.bin
|
||||||
/grub-core/lib/gnulib
|
/grub-core/lib/gnulib
|
||||||
/grub-core/lib/libgcrypt-grub
|
/grub-core/lib/libgcrypt-grub
|
||||||
|
/grub-core/lib/libtasn1-grub
|
||||||
/grub-core/modinfo.sh
|
/grub-core/modinfo.sh
|
||||||
/grub-core/rs_decoder.h
|
/grub-core/rs_decoder.h
|
||||||
/grub-core/symlist.c
|
/grub-core/symlist.c
|
||||||
/grub-core/symlist.h
|
/grub-core/symlist.h
|
||||||
|
/grub-core/tests/asn1/tests
|
||||||
/grub-core/trigtables.c
|
/grub-core/trigtables.c
|
||||||
/grub-core/unidata.c
|
/grub-core/unidata.c
|
||||||
/grub-editenv
|
/grub-editenv
|
||||||
|
@ -169,6 +171,8 @@ widthspec.bin
|
||||||
/grub-ofpathname.exe
|
/grub-ofpathname.exe
|
||||||
/grub-probe
|
/grub-probe
|
||||||
/grub-probe.exe
|
/grub-probe.exe
|
||||||
|
/grub-protect
|
||||||
|
/grub-protect.exe
|
||||||
/grub-reboot
|
/grub-reboot
|
||||||
/grub-render-label
|
/grub-render-label
|
||||||
/grub-render-label.exe
|
/grub-render-label.exe
|
||||||
|
|
9
INSTALL
9
INSTALL
|
@ -74,18 +74,19 @@ Prerequisites for make-check:
|
||||||
* wamerican, for grub-fs-tester
|
* wamerican, for grub-fs-tester
|
||||||
* mtools, FAT tools for EFI platforms
|
* mtools, FAT tools for EFI platforms
|
||||||
* xfonts-unifont, for the functional tests
|
* xfonts-unifont, for the functional tests
|
||||||
|
* swtpm-tools and tpm2-tools, for TPM2 key protector tests
|
||||||
|
|
||||||
* If running a Linux kernel the following modules must be loaded:
|
* If running a Linux kernel the following modules must be loaded:
|
||||||
- fuse, loop
|
- fuse, loop
|
||||||
- btrfs, ext4, f2fs, fat, hfs, hfsplus, jfs, mac-roman, minix, nilfs2,
|
- btrfs, erofs, ext4, f2fs, fat, hfs, hfsplus, jfs, mac-roman, minix, nilfs2,
|
||||||
reiserfs, udf, xfs
|
reiserfs, udf, xfs
|
||||||
- On newer kernels, the exfat kernel modules may be used instead of the
|
- On newer kernels, the exfat kernel modules may be used instead of the
|
||||||
exfat FUSE filesystem
|
exfat FUSE filesystem
|
||||||
* The following are Debian named packages required mostly for the full
|
* The following are Debian named packages required mostly for the full
|
||||||
suite of filesystem testing (but some are needed by other tests as well):
|
suite of filesystem testing (but some are needed by other tests as well):
|
||||||
- btrfs-progs, dosfstools, e2fsprogs, exfat-utils, f2fs-tools, genromfs,
|
- btrfs-progs, dosfstools, e2fsprogs, erofs-utils, exfatprogs, exfat-fuse,
|
||||||
hfsprogs, jfsutils, nilfs-tools, ntfs-3g, reiserfsprogs, squashfs-tools,
|
f2fs-tools, genromfs, hfsprogs, jfsutils, nilfs-tools, ntfs-3g,
|
||||||
reiserfsprogs, udftools, xfsprogs, zfs-fuse
|
reiserfsprogs, squashfs-tools, reiserfsprogs, udftools, xfsprogs, zfs-fuse
|
||||||
- exfat-fuse, if not using the exfat kernel module
|
- exfat-fuse, if not using the exfat kernel module
|
||||||
- gzip, lzop, xz-utils
|
- gzip, lzop, xz-utils
|
||||||
- attr, cpio, g++, gawk, parted, recode, tar, util-linux
|
- attr, cpio, g++, gawk, parted, recode, tar, util-linux
|
||||||
|
|
|
@ -40,6 +40,7 @@ library = {
|
||||||
common = grub-core/disk/luks.c;
|
common = grub-core/disk/luks.c;
|
||||||
common = grub-core/disk/luks2.c;
|
common = grub-core/disk/luks2.c;
|
||||||
common = grub-core/disk/geli.c;
|
common = grub-core/disk/geli.c;
|
||||||
|
common = grub-core/disk/key_protector.c;
|
||||||
common = grub-core/disk/cryptodisk.c;
|
common = grub-core/disk/cryptodisk.c;
|
||||||
common = grub-core/disk/AFSplitter.c;
|
common = grub-core/disk/AFSplitter.c;
|
||||||
common = grub-core/lib/pbkdf2.c;
|
common = grub-core/lib/pbkdf2.c;
|
||||||
|
@ -98,6 +99,7 @@ library = {
|
||||||
common = grub-core/fs/cpio_be.c;
|
common = grub-core/fs/cpio_be.c;
|
||||||
common = grub-core/fs/odc.c;
|
common = grub-core/fs/odc.c;
|
||||||
common = grub-core/fs/newc.c;
|
common = grub-core/fs/newc.c;
|
||||||
|
common = grub-core/fs/erofs.c;
|
||||||
common = grub-core/fs/ext2.c;
|
common = grub-core/fs/ext2.c;
|
||||||
common = grub-core/fs/fat.c;
|
common = grub-core/fs/fat.c;
|
||||||
common = grub-core/fs/exfat.c;
|
common = grub-core/fs/exfat.c;
|
||||||
|
@ -206,6 +208,32 @@ program = {
|
||||||
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
program = {
|
||||||
|
name = grub-protect;
|
||||||
|
mansection = 1;
|
||||||
|
|
||||||
|
common = grub-core/kern/emu/argp_common.c;
|
||||||
|
common = grub-core/osdep/init.c;
|
||||||
|
common = grub-core/lib/tss2/buffer.c;
|
||||||
|
common = grub-core/lib/tss2/tss2_mu.c;
|
||||||
|
common = grub-core/lib/tss2/tpm2_cmd.c;
|
||||||
|
common = grub-core/commands/tpm2_key_protector/args.c;
|
||||||
|
common = grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c;
|
||||||
|
common = util/grub-protect.c;
|
||||||
|
common = util/probe.c;
|
||||||
|
|
||||||
|
cflags = '-I$(srcdir)/grub-core/lib/tss2 -I$(srcdir)/grub-core/commands/tpm2_key_protector';
|
||||||
|
|
||||||
|
ldadd = libgrubmods.a;
|
||||||
|
ldadd = libgrubgcry.a;
|
||||||
|
ldadd = libgrubkern.a;
|
||||||
|
ldadd = grub-core/lib/gnulib/libgnu.a;
|
||||||
|
ldadd = '$(LIBTASN1)';
|
||||||
|
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||||
|
|
||||||
|
condition = COND_GRUB_PROTECT;
|
||||||
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
name = grub-mkrelpath;
|
name = grub-mkrelpath;
|
||||||
mansection = 1;
|
mansection = 1;
|
||||||
|
@ -763,6 +791,12 @@ script = {
|
||||||
dependencies = 'garbage-gen$(BUILD_EXEEXT)';
|
dependencies = 'garbage-gen$(BUILD_EXEEXT)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
testcase = native;
|
||||||
|
name = erofs_test;
|
||||||
|
common = tests/erofs_test.in;
|
||||||
|
};
|
||||||
|
|
||||||
script = {
|
script = {
|
||||||
testcase = native;
|
testcase = native;
|
||||||
name = ext234_test;
|
name = ext234_test;
|
||||||
|
@ -1250,6 +1284,18 @@ script = {
|
||||||
common = tests/luks2_test.in;
|
common = tests/luks2_test.in;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
testcase = native;
|
||||||
|
name = asn1_test;
|
||||||
|
common = tests/asn1_test.in;
|
||||||
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
testcase = native;
|
||||||
|
name = tpm2_key_protector_test;
|
||||||
|
common = tests/tpm2_key_protector_test.in;
|
||||||
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
testcase = native;
|
testcase = native;
|
||||||
name = example_unit_test;
|
name = example_unit_test;
|
||||||
|
|
33
autogen.sh
33
autogen.sh
|
@ -51,6 +51,39 @@ for x in mpi-asm-defs.h mpih-add1.c mpih-sub1.c mpih-mul1.c mpih-mul2.c mpih-mul
|
||||||
cp grub-core/lib/libgcrypt-grub/mpi/generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x"
|
cp grub-core/lib/libgcrypt-grub/mpi/generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "Importing libtasn1..."
|
||||||
|
if [ -d grub-core/lib/libtasn1-grub ]; then
|
||||||
|
rm -rf grub-core/lib/libtasn1-grub
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p grub-core/lib/libtasn1-grub/lib
|
||||||
|
cp grub-core/lib/libtasn1/lib/*.[ch] grub-core/lib/libtasn1-grub/lib
|
||||||
|
cp grub-core/lib/libtasn1/libtasn1.h grub-core/lib/libtasn1-grub/
|
||||||
|
|
||||||
|
if [ -d grub-core/tests/asn1/tests ]; then
|
||||||
|
rm -rf grub-core/tests/asn1/tests
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir grub-core/tests/asn1/tests
|
||||||
|
cp grub-core/lib/libtasn1/tests/*.[ch] grub-core/tests/asn1/tests
|
||||||
|
|
||||||
|
for patch in \
|
||||||
|
0001-libtasn1-disable-code-not-needed-in-grub.patch \
|
||||||
|
0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch \
|
||||||
|
0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch \
|
||||||
|
0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch \
|
||||||
|
0005-libtasn1-Use-grub_divmod64-for-division.patch \
|
||||||
|
0006-libtasn1-fix-the-potential-buffer-overrun.patch \
|
||||||
|
0007-asn1_test-include-asn1_test.h-only.patch \
|
||||||
|
0008-asn1_test-rename-the-main-functions-to-the-test-name.patch \
|
||||||
|
0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch \
|
||||||
|
0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch \
|
||||||
|
0011-asn1_test-print-the-error-messages-with-grub_printf.patch \
|
||||||
|
0012-asn1_test-use-the-grub-specific-functions-and-types.patch \
|
||||||
|
0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch ; do
|
||||||
|
patch -p1 -i grub-core/lib/libtasn1-patches/$patch
|
||||||
|
done
|
||||||
|
|
||||||
echo "Generating Automake input..."
|
echo "Generating Automake input..."
|
||||||
|
|
||||||
# Automake doesn't like including files from a path outside the project.
|
# Automake doesn't like including files from a path outside the project.
|
||||||
|
|
|
@ -84,7 +84,14 @@ bootstrap_post_import_hook () {
|
||||||
# Instead of patching our gnulib and therefore maintaining a fork, submit
|
# Instead of patching our gnulib and therefore maintaining a fork, submit
|
||||||
# changes to gnulib and update the hash above when they've merged. Do not
|
# changes to gnulib and update the hash above when they've merged. Do not
|
||||||
# add new patches here.
|
# add new patches here.
|
||||||
patch -d grub-core/lib/gnulib -p2 < grub-core/lib/gnulib-patches/fix-width.patch
|
for patchname in fix-width \
|
||||||
|
fix-regcomp-resource-leak \
|
||||||
|
fix-regexec-resource-leak \
|
||||||
|
fix-gcc-15-compile \
|
||||||
|
fix-unused-value; do
|
||||||
|
patch -d grub-core/lib/gnulib -p2 \
|
||||||
|
< "grub-core/lib/gnulib-patches/$patchname.patch"
|
||||||
|
done
|
||||||
|
|
||||||
for patchname in \
|
for patchname in \
|
||||||
0001-Support-POTFILES-shell \
|
0001-Support-POTFILES-shell \
|
||||||
|
|
|
@ -111,6 +111,7 @@ MOD_FILES =
|
||||||
MODULE_FILES =
|
MODULE_FILES =
|
||||||
MARKER_FILES =
|
MARKER_FILES =
|
||||||
KERNEL_HEADER_FILES =
|
KERNEL_HEADER_FILES =
|
||||||
|
EXTRA_DEPS =
|
||||||
|
|
||||||
bin_SCRIPTS =
|
bin_SCRIPTS =
|
||||||
bin_PROGRAMS =
|
bin_PROGRAMS =
|
||||||
|
|
|
@ -29,12 +29,19 @@ EXTRA_DIST += grub-core/genemuinit.sh
|
||||||
EXTRA_DIST += grub-core/genemuinitheader.sh
|
EXTRA_DIST += grub-core/genemuinitheader.sh
|
||||||
|
|
||||||
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
|
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
|
||||||
|
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-resource-leak.patch
|
||||||
|
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-resource-leak.patch
|
||||||
|
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-gcc-15-compile.patch
|
||||||
|
EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
|
||||||
|
|
||||||
EXTRA_DIST += grub-core/lib/libgcrypt
|
EXTRA_DIST += grub-core/lib/libgcrypt
|
||||||
EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic
|
EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic
|
||||||
EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h')
|
EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h')
|
||||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h')
|
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h')
|
||||||
EXTRA_DIST += grub-core/efiemu/runtime/config.h
|
EXTRA_DIST += grub-core/efiemu/runtime/config.h
|
||||||
|
EXTRA_DIST += grub-core/tests/asn1/asn1_test.h
|
||||||
|
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/tests/asn1/tests -name '*.h')
|
||||||
|
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/commands/tpm2_key_protector -name '*.h')
|
||||||
|
|
||||||
EXTRA_DIST += grub-core/lib/LzmaDec.c
|
EXTRA_DIST += grub-core/lib/LzmaDec.c
|
||||||
|
|
||||||
|
|
72
configure.ac
72
configure.ac
|
@ -34,7 +34,7 @@ dnl "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for
|
||||||
dnl the target type. See INSTALL for full list of variables and
|
dnl the target type. See INSTALL for full list of variables and
|
||||||
dnl description of the relationships between them.
|
dnl description of the relationships between them.
|
||||||
|
|
||||||
AC_INIT([GRUB],[2.12],[bug-grub@gnu.org])
|
AC_INIT([GRUB],[2.13],[bug-grub@gnu.org])
|
||||||
|
|
||||||
AS_CASE(["$ERROR_PLATFORM_NOT_SUPPORT_SSP"],
|
AS_CASE(["$ERROR_PLATFORM_NOT_SUPPORT_SSP"],
|
||||||
[n | no | nO | N | No | NO], [ERROR_PLATFORM_NOT_SUPPORT_SSP=no],
|
[n | no | nO | N | No | NO], [ERROR_PLATFORM_NOT_SUPPORT_SSP=no],
|
||||||
|
@ -76,6 +76,7 @@ grub_TRANSFORM([grub-mkpasswd-pbkdf2])
|
||||||
grub_TRANSFORM([grub-mkrelpath])
|
grub_TRANSFORM([grub-mkrelpath])
|
||||||
grub_TRANSFORM([grub-mkrescue])
|
grub_TRANSFORM([grub-mkrescue])
|
||||||
grub_TRANSFORM([grub-probe])
|
grub_TRANSFORM([grub-probe])
|
||||||
|
grub_TRANSFORM([grub-protect])
|
||||||
grub_TRANSFORM([grub-reboot])
|
grub_TRANSFORM([grub-reboot])
|
||||||
grub_TRANSFORM([grub-script-check])
|
grub_TRANSFORM([grub-script-check])
|
||||||
grub_TRANSFORM([grub-set-default])
|
grub_TRANSFORM([grub-set-default])
|
||||||
|
@ -802,6 +803,17 @@ if test "x$target_cpu" = xmips || test "x$target_cpu" = xmipsel ; then
|
||||||
if test "x$grub_cv_cc_mflush_func" = xyes; then
|
if test "x$grub_cv_cc_mflush_func" = xyes; then
|
||||||
TARGET_CFLAGS="$TARGET_CFLAGS -mflush-func=grub_red_herring"
|
TARGET_CFLAGS="$TARGET_CFLAGS -mflush-func=grub_red_herring"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether -mno-gpopt works], [grub_cv_cc_mno_gpopt], [
|
||||||
|
CFLAGS="$TARGET_CFLAGS -mno-gpopt -Werror"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||||
|
[grub_cv_cc_mno_gpopt=yes],
|
||||||
|
[grub_cv_cc_mno_gpopt=no])
|
||||||
|
])
|
||||||
|
|
||||||
|
if test "x$grub_cv_cc_mno_gpopt" = xyes; then
|
||||||
|
TARGET_CFLAGS="$TARGET_CFLAGS -mno-gpopt"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -901,6 +913,31 @@ if test "x$target_cpu" = xloongarch64; then
|
||||||
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs"
|
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$target_cpu" = xriscv64 || test "x$target_cpu" = xriscv32; then
|
||||||
|
AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [
|
||||||
|
grub_cv_target_cc_mno_relax=no
|
||||||
|
for cand in "-mno-relax" "-Wa,-mno-relax"; do
|
||||||
|
if test x"$grub_cv_target_cc_mno_relax" != xno ; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
CFLAGS="$TARGET_CFLAGS $cand -Werror"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
asm (".globl start; start:");
|
||||||
|
void __main (void);
|
||||||
|
void __main (void) {}
|
||||||
|
int main (void);
|
||||||
|
]], [[]])], [grub_cv_target_cc_mno_relax="$cand"], [])
|
||||||
|
done
|
||||||
|
])
|
||||||
|
|
||||||
|
CFLAGS="$TARGET_CFLAGS"
|
||||||
|
|
||||||
|
if test x"$grub_cv_target_cc_mno_relax" != xno ; then
|
||||||
|
TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mno_relax"
|
||||||
|
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_mno_relax"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# GRUB doesn't use float or doubles at all. Yet some toolchains may decide
|
# GRUB doesn't use float or doubles at all. Yet some toolchains may decide
|
||||||
# that floats are a good fit to run instead of what's written in the code.
|
# that floats are a good fit to run instead of what's written in the code.
|
||||||
# Given that floating point unit is disabled (if present to begin with)
|
# Given that floating point unit is disabled (if present to begin with)
|
||||||
|
@ -1847,7 +1884,7 @@ if test "x$with_dejavufont" = x; then
|
||||||
# search in well-known directories
|
# search in well-known directories
|
||||||
if test x"$starfield_excuse" = x; then
|
if test x"$starfield_excuse" = x; then
|
||||||
for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
|
for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
|
||||||
for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/pkg/share/fonts/X11/TTF /usr/local/share/fonts/dejavu /usr/X11R6/lib/X11/fonts/TTF; do
|
for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/pkg/share/fonts/X11/TTF /usr/local/share/fonts/dejavu /usr/X11R6/lib/X11/fonts/TTF /usr/share/fonts/dejavu-sans-fonts /usr/share/fonts/truetype/dejavu; do
|
||||||
if test -f "$dir/DejaVuSans.$ext"; then
|
if test -f "$dir/DejaVuSans.$ext"; then
|
||||||
DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
|
DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
|
||||||
break 2
|
break 2
|
||||||
|
@ -1875,7 +1912,7 @@ AC_ARG_WITH([unifont],
|
||||||
|
|
||||||
if test "x$with_unifont" = x; then
|
if test "x$with_unifont" = x; then
|
||||||
# search in well-known directories
|
# search in well-known directories
|
||||||
for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
|
for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz otf otf.gz; do
|
||||||
for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont /usr/share/fonts/uni /usr/share/fonts/truetype/unifont /usr/share/fonts/misc /usr/pkg/share/fonts/X11/misc /usr/local/share/fonts/gnu-unifont /usr/local/share/fonts/unifont; do
|
for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont /usr/share/fonts/uni /usr/share/fonts/truetype/unifont /usr/share/fonts/misc /usr/pkg/share/fonts/X11/misc /usr/local/share/fonts/gnu-unifont /usr/local/share/fonts/unifont; do
|
||||||
if test -f "$dir/unifont.$ext"; then
|
if test -f "$dir/unifont.$ext"; then
|
||||||
md5="$(md5sum "$dir/unifont.$ext"|awk '{ print $1; }')"
|
md5="$(md5sum "$dir/unifont.$ext"|awk '{ print $1; }')"
|
||||||
|
@ -2057,6 +2094,29 @@ fi
|
||||||
AC_SUBST([LIBZFS])
|
AC_SUBST([LIBZFS])
|
||||||
AC_SUBST([LIBNVPAIR])
|
AC_SUBST([LIBNVPAIR])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([grub-protect],
|
||||||
|
[AS_HELP_STRING([--enable-grub-protect],
|
||||||
|
[build and install the `grub-protect' utility (default=guessed)])])
|
||||||
|
if test x"$enable_grub_protect" = xno ; then
|
||||||
|
grub_protect_excuse="explicitly disabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBTASN1=
|
||||||
|
if test x"$grub_protect_excuse" = x ; then
|
||||||
|
AC_CHECK_LIB([tasn1], [asn1_write_value], [LIBTASN1="-ltasn1"], [grub_protect_excuse="need libtasn1 library"])
|
||||||
|
fi
|
||||||
|
AC_SUBST([LIBTASN1])
|
||||||
|
|
||||||
|
if test x"$enable_grub_protect" = xyes && test x"$grub_protect_excuse" != x ; then
|
||||||
|
AC_MSG_ERROR([grub-protect was explicitly requested but can't be compiled ($grub_protect_excuse)])
|
||||||
|
fi
|
||||||
|
if test x"$grub_protect_excuse" = x ; then
|
||||||
|
enable_grub_protect=yes
|
||||||
|
else
|
||||||
|
enable_grub_protect=no
|
||||||
|
fi
|
||||||
|
AC_SUBST([enable_grub_protect])
|
||||||
|
|
||||||
LIBS=""
|
LIBS=""
|
||||||
|
|
||||||
AC_SUBST([FONT_SOURCE])
|
AC_SUBST([FONT_SOURCE])
|
||||||
|
@ -2173,6 +2233,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
|
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
|
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes])
|
AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes])
|
||||||
|
AM_CONDITIONAL([COND_GRUB_PROTECT], [test x$enable_grub_protect = xyes])
|
||||||
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
|
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
|
||||||
if test x$FONT_SOURCE != x ; then
|
if test x$FONT_SOURCE != x ; then
|
||||||
HAVE_FONT_SOURCE=1
|
HAVE_FONT_SOURCE=1
|
||||||
|
@ -2300,6 +2361,11 @@ echo grub-mount: Yes
|
||||||
else
|
else
|
||||||
echo grub-mount: No "($grub_mount_excuse)"
|
echo grub-mount: No "($grub_mount_excuse)"
|
||||||
fi
|
fi
|
||||||
|
if [ x"$grub_protect_excuse" = x ]; then
|
||||||
|
echo grub-protect: Yes
|
||||||
|
else
|
||||||
|
echo grub-protect: No "($grub_protect_excuse)"
|
||||||
|
fi
|
||||||
if [ x"$starfield_excuse" = x ]; then
|
if [ x"$starfield_excuse" = x ]; then
|
||||||
echo starfield theme: Yes
|
echo starfield theme: Yes
|
||||||
echo With DejaVuSans font from $DJVU_FONT_SOURCE
|
echo With DejaVuSans font from $DJVU_FONT_SOURCE
|
||||||
|
|
|
@ -506,6 +506,7 @@ to update it.
|
||||||
* Gnulib::
|
* Gnulib::
|
||||||
* jsmn::
|
* jsmn::
|
||||||
* minilzo::
|
* minilzo::
|
||||||
|
* libtasn1::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Gnulib
|
@node Gnulib
|
||||||
|
@ -596,6 +597,40 @@ cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
|
||||||
rm -r minilzo-2.10*
|
rm -r minilzo-2.10*
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@node libtasn1
|
||||||
|
@section libtasn1
|
||||||
|
|
||||||
|
libtasn1 is a library providing Abstract Syntax Notation One (ASN.1, as
|
||||||
|
specified by the X.680 ITU-T recommendation) parsing and structures management,
|
||||||
|
and Distinguished Encoding Rules (DER, as per X.690) encoding and decoding
|
||||||
|
functions.
|
||||||
|
|
||||||
|
To upgrade to a new version of the libtasn1 library, download the release
|
||||||
|
tarball and copy the files into the target directory:
|
||||||
|
|
||||||
|
@example
|
||||||
|
curl -L -O https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.19.0.tar.gz
|
||||||
|
tar xvzf libtasn1-4.19.0.tar.gz
|
||||||
|
rm -rf grub-core/lib/libtasn1
|
||||||
|
mkdir -p grub-core/lib/libtasn1/lib
|
||||||
|
mkdir -p grub-core/lib/libtasn1/tests
|
||||||
|
cp libtasn1-4.19.0/@{README.md,COPYING@} grub-core/lib/libtasn1
|
||||||
|
cp libtasn1-4.19.0/lib/@{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h@} grub-core/lib/libtasn1/lib
|
||||||
|
cp libtasn1-4.19.0/lib/includes/libtasn1.h grub-core/lib/libtasn1
|
||||||
|
cp libtasn1-4.19.0/tests/@{CVE-2018-1000654-1_asn1_tab.h,CVE-2018-1000654-2_asn1_tab.h,CVE-2018-1000654.c,object-id-decoding.c,object-id-encoding.c,octet-string.c,reproducers.c,Test_overflow.c,Test_simple.c,Test_strings.c@} grub-core/lib/libtasn1/tests
|
||||||
|
rm -rf libtasn1-4.19.0*
|
||||||
|
@end example
|
||||||
|
|
||||||
|
After upgrading the library, it may be necessary to apply the patches in
|
||||||
|
@file{grub-core/lib/libtasn1-patches/} to adjust the code to be compatible with
|
||||||
|
GRUB. These patches were needed to use the current version of libtasn1. The
|
||||||
|
existing patches may not apply cleanly, apply at all, or even be needed for a
|
||||||
|
newer version of the library, and other patches may be needed due to changes in
|
||||||
|
the newer version. If existing patches need to be refreshed to apply cleanly,
|
||||||
|
please include updated patches as part of the a patch set sent to the list.
|
||||||
|
If new patches are needed or existing patches are not needed, also please send
|
||||||
|
additions or removals as part of any patch set upgrading libtasn1.
|
||||||
|
|
||||||
@node Debugging
|
@node Debugging
|
||||||
@chapter Debugging
|
@chapter Debugging
|
||||||
|
|
||||||
|
|
3092
docs/grub.texi
3092
docs/grub.texi
File diff suppressed because it is too large
Load diff
4
docs/man/grub-protect.h2m
Normal file
4
docs/man/grub-protect.h2m
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[NAME]
|
||||||
|
grub-protect \- protect a disk key with a key protector
|
||||||
|
[DESCRIPTION]
|
||||||
|
grub-protect helps to protect a disk encryption key with a specified key protector.
|
11
gentpl.py
11
gentpl.py
|
@ -631,7 +631,10 @@ def platform_values(defn, platform, suffix):
|
||||||
def extra_dist(defn):
|
def extra_dist(defn):
|
||||||
return foreach_value(defn, "extra_dist", lambda value: value + " ")
|
return foreach_value(defn, "extra_dist", lambda value: value + " ")
|
||||||
|
|
||||||
def platform_sources(defn, p): return platform_values(defn, p, "")
|
def extra_dep(defn):
|
||||||
|
return foreach_value(defn, "depends", lambda value: value + " ")
|
||||||
|
|
||||||
|
def platform_sources(defn, p): return platform_values(defn, p, "_head") + platform_values(defn, p, "")
|
||||||
def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist")
|
def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist")
|
||||||
|
|
||||||
def platform_startup(defn, p): return platform_specific_values(defn, p, "_startup", "startup")
|
def platform_startup(defn, p): return platform_specific_values(defn, p, "_startup", "startup")
|
||||||
|
@ -657,7 +660,7 @@ def first_time(defn, snippet):
|
||||||
def is_platform_independent(defn):
|
def is_platform_independent(defn):
|
||||||
if 'enable' in defn:
|
if 'enable' in defn:
|
||||||
return False
|
return False
|
||||||
for suffix in [ "", "_nodist" ]:
|
for suffix in [ "", "_head", "_nodist" ]:
|
||||||
template = platform_values(defn, GRUB_PLATFORMS[0], suffix)
|
template = platform_values(defn, GRUB_PLATFORMS[0], suffix)
|
||||||
for platform in GRUB_PLATFORMS[1:]:
|
for platform in GRUB_PLATFORMS[1:]:
|
||||||
if template != platform_values(defn, platform, suffix):
|
if template != platform_values(defn, platform, suffix):
|
||||||
|
@ -699,6 +702,10 @@ def module(defn, platform):
|
||||||
gvar_add("MOD_FILES", name + ".mod")
|
gvar_add("MOD_FILES", name + ".mod")
|
||||||
gvar_add("MARKER_FILES", name + ".marker")
|
gvar_add("MARKER_FILES", name + ".marker")
|
||||||
gvar_add("CLEANFILES", name + ".marker")
|
gvar_add("CLEANFILES", name + ".marker")
|
||||||
|
|
||||||
|
for dep in defn.find_all("depends"):
|
||||||
|
gvar_add("EXTRA_DEPS", "depends " + name + " " + dep + ":")
|
||||||
|
|
||||||
output("""
|
output("""
|
||||||
""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES)
|
""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES)
|
||||||
$(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1)
|
$(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1)
|
||||||
|
|
|
@ -90,6 +90,7 @@ endif
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/key_protector.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||||
|
@ -454,8 +455,11 @@ crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst
|
||||||
platform_DATA += crypto.lst
|
platform_DATA += crypto.lst
|
||||||
CLEANFILES += crypto.lst
|
CLEANFILES += crypto.lst
|
||||||
|
|
||||||
syminfo.lst: gensyminfo.sh kernel_syms.lst $(top_srcdir)/grub-core/extra_deps.lst $(MODULE_FILES)
|
extra_deps.lst:
|
||||||
cat kernel_syms.lst $(top_srcdir)/grub-core/extra_deps.lst > $@.new
|
@echo $(EXTRA_DEPS) | sed "s/\s*:\s*/\n/g" > $@
|
||||||
|
|
||||||
|
syminfo.lst: gensyminfo.sh kernel_syms.lst extra_deps.lst $(MODULE_FILES)
|
||||||
|
cat kernel_syms.lst extra_deps.lst > $@.new
|
||||||
for m in $(MODULE_FILES); do \
|
for m in $(MODULE_FILES); do \
|
||||||
sh $< $$m >> $@.new || exit 1; \
|
sh $< $$m >> $@.new || exit 1; \
|
||||||
done
|
done
|
||||||
|
@ -465,7 +469,7 @@ syminfo.lst: gensyminfo.sh kernel_syms.lst $(top_srcdir)/grub-core/extra_deps.ls
|
||||||
moddep.lst: syminfo.lst genmoddep.awk video.lst
|
moddep.lst: syminfo.lst genmoddep.awk video.lst
|
||||||
cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1)
|
cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1)
|
||||||
platform_DATA += moddep.lst
|
platform_DATA += moddep.lst
|
||||||
CLEANFILES += config.log syminfo.lst moddep.lst
|
CLEANFILES += config.log syminfo.lst moddep.lst extra_deps.lst
|
||||||
|
|
||||||
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
|
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
|
||||||
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
|
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
|
||||||
|
|
|
@ -536,7 +536,7 @@ image = {
|
||||||
|
|
||||||
image = {
|
image = {
|
||||||
name = xz_decompress;
|
name = xz_decompress;
|
||||||
mips = boot/mips/startup_raw.S;
|
mips_head = boot/mips/startup_raw.S;
|
||||||
common = boot/decompressor/minilib.c;
|
common = boot/decompressor/minilib.c;
|
||||||
common = boot/decompressor/xz.c;
|
common = boot/decompressor/xz.c;
|
||||||
common = lib/xzembed/xz_dec_bcj.c;
|
common = lib/xzembed/xz_dec_bcj.c;
|
||||||
|
@ -554,7 +554,7 @@ image = {
|
||||||
|
|
||||||
image = {
|
image = {
|
||||||
name = none_decompress;
|
name = none_decompress;
|
||||||
mips = boot/mips/startup_raw.S;
|
mips_head = boot/mips/startup_raw.S;
|
||||||
common = boot/decompressor/none.c;
|
common = boot/decompressor/none.c;
|
||||||
|
|
||||||
cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
|
cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
|
||||||
|
@ -714,12 +714,16 @@ module = {
|
||||||
name = cmostest;
|
name = cmostest;
|
||||||
common = commands/i386/cmostest.c;
|
common = commands/i386/cmostest.c;
|
||||||
enable = cmos;
|
enable = cmos;
|
||||||
|
enable = i386_efi;
|
||||||
|
enable = x86_64_efi;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = cmosdump;
|
name = cmosdump;
|
||||||
common = commands/i386/cmosdump.c;
|
common = commands/i386/cmosdump.c;
|
||||||
enable = cmos;
|
enable = cmos;
|
||||||
|
enable = i386_efi;
|
||||||
|
enable = x86_64_efi;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -1278,6 +1282,11 @@ module = {
|
||||||
common = disk/raid6_recover.c;
|
common = disk/raid6_recover.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = key_protector;
|
||||||
|
common = disk/key_protector.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = scsi;
|
name = scsi;
|
||||||
common = disk/scsi.c;
|
common = disk/scsi.c;
|
||||||
|
@ -1438,6 +1447,11 @@ module = {
|
||||||
common = fs/odc.c;
|
common = fs/odc.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = erofs;
|
||||||
|
common = fs/erofs.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = ext2;
|
name = ext2;
|
||||||
common = fs/ext2.c;
|
common = fs/ext2.c;
|
||||||
|
@ -1592,6 +1606,7 @@ module = {
|
||||||
common = fs/zfs/zfs_lz4.c;
|
common = fs/zfs/zfs_lz4.c;
|
||||||
common = fs/zfs/zfs_sha256.c;
|
common = fs/zfs/zfs_sha256.c;
|
||||||
common = fs/zfs/zfs_fletcher.c;
|
common = fs/zfs/zfs_fletcher.c;
|
||||||
|
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -2238,6 +2253,10 @@ module = {
|
||||||
common = tests/videotest_checksum.c;
|
common = tests/videotest_checksum.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These tests fail depending on the version of unifont. As we don't distribute
|
||||||
|
* our own unifont it fails for most users. Disable them so that they don't mask
|
||||||
|
* real failures. They can be reinstated once we solve unifont problem.
|
||||||
module = {
|
module = {
|
||||||
name = gfxterm_menu;
|
name = gfxterm_menu;
|
||||||
common = tests/gfxterm_menu.c;
|
common = tests/gfxterm_menu.c;
|
||||||
|
@ -2247,6 +2266,7 @@ module = {
|
||||||
name = cmdline_cat_test;
|
name = cmdline_cat_test;
|
||||||
common = tests/cmdline_cat_test.c;
|
common = tests/cmdline_cat_test.c;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = bitmap;
|
name = bitmap;
|
||||||
|
@ -2552,6 +2572,34 @@ module = {
|
||||||
enable = efi;
|
enable = efi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = tss2;
|
||||||
|
common = lib/tss2/buffer.c;
|
||||||
|
common = lib/tss2/tss2_mu.c;
|
||||||
|
common = lib/tss2/tpm2_cmd.c;
|
||||||
|
common = lib/tss2/tss2.c;
|
||||||
|
efi = lib/efi/tcg2.c;
|
||||||
|
emu = lib/tss2/tcg2_emu.c;
|
||||||
|
powerpc_ieee1275 = lib/ieee1275/tcg2.c;
|
||||||
|
enable = efi;
|
||||||
|
enable = emu;
|
||||||
|
enable = powerpc_ieee1275;
|
||||||
|
cppflags = '-I$(srcdir)/lib/tss2';
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = tpm2_key_protector;
|
||||||
|
common = commands/tpm2_key_protector/args.c;
|
||||||
|
common = commands/tpm2_key_protector/module.c;
|
||||||
|
common = commands/tpm2_key_protector/tpm2key.c;
|
||||||
|
common = commands/tpm2_key_protector/tpm2key_asn1_tab.c;
|
||||||
|
/* The plaform support of tpm2_key_protector depends on the tcg2 implementation in tss2. */
|
||||||
|
enable = efi;
|
||||||
|
enable = emu;
|
||||||
|
enable = powerpc_ieee1275;
|
||||||
|
cppflags = '-I$(srcdir)/lib/tss2 -I$(srcdir)/lib/libtasn1-grub';
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = tr;
|
name = tr;
|
||||||
common = commands/tr.c;
|
common = commands/tr.c;
|
||||||
|
@ -2594,4 +2642,35 @@ module = {
|
||||||
name = bli;
|
name = bli;
|
||||||
efi = commands/bli.c;
|
efi = commands/bli.c;
|
||||||
enable = efi;
|
enable = efi;
|
||||||
|
depends = part_gpt;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = asn1;
|
||||||
|
common = lib/libtasn1-grub/lib/decoding.c;
|
||||||
|
common = lib/libtasn1-grub/lib/coding.c;
|
||||||
|
common = lib/libtasn1-grub/lib/element.c;
|
||||||
|
common = lib/libtasn1-grub/lib/structure.c;
|
||||||
|
common = lib/libtasn1-grub/lib/parser_aux.c;
|
||||||
|
common = lib/libtasn1-grub/lib/gstr.c;
|
||||||
|
common = lib/libtasn1-grub/lib/errors.c;
|
||||||
|
common = lib/libtasn1_wrap/wrap.c;
|
||||||
|
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
|
||||||
|
/* -Wno-type-limits comes from configure.ac of libtasn1 */
|
||||||
|
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1-grub -I$(srcdir)/lib/libtasn1-grub/lib -Wno-type-limits';
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = asn1_test;
|
||||||
|
common = tests/asn1/tests/CVE-2018-1000654.c;
|
||||||
|
common = tests/asn1/tests/object-id-decoding.c;
|
||||||
|
common = tests/asn1/tests/object-id-encoding.c;
|
||||||
|
common = tests/asn1/tests/octet-string.c;
|
||||||
|
common = tests/asn1/tests/reproducers.c;
|
||||||
|
common = tests/asn1/tests/Test_overflow.c;
|
||||||
|
common = tests/asn1/tests/Test_simple.c;
|
||||||
|
common = tests/asn1/tests/Test_strings.c;
|
||||||
|
common = tests/asn1/asn1_test.c;
|
||||||
|
cflags = '-Wno-uninitialized';
|
||||||
|
cppflags = '-I$(srcdir)/lib/libtasn1-grub -I$(srcdir)/tests/asn1/';
|
||||||
};
|
};
|
||||||
|
|
|
@ -218,7 +218,7 @@ enum
|
||||||
|
|
||||||
#define GRUB_EHCI_TERMINATE (1<<0)
|
#define GRUB_EHCI_TERMINATE (1<<0)
|
||||||
|
|
||||||
#define GRUB_EHCI_TOGGLE (1<<31)
|
#define GRUB_EHCI_TOGGLE ((grub_uint32_t) 1<<31)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,20 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTION_EXCLUDE = 0,
|
||||||
|
OPTION_LOAD_ONLY,
|
||||||
|
OPTION_V1,
|
||||||
|
OPTION_V2,
|
||||||
|
OPTION_OEMID,
|
||||||
|
OPTION_OEMTABLE,
|
||||||
|
OPTION_OEMTABLEREV,
|
||||||
|
OPTION_OEMTABLECREATOR,
|
||||||
|
OPTION_OEMTABLECREATORREV,
|
||||||
|
OPTION_NO_EBDA
|
||||||
|
};
|
||||||
|
|
||||||
static const struct grub_arg_option options[] = {
|
static const struct grub_arg_option options[] = {
|
||||||
{"exclude", 'x', 0,
|
{"exclude", 'x', 0,
|
||||||
N_("Don't load host tables specified by comma-separated list."),
|
N_("Don't load host tables specified by comma-separated list."),
|
||||||
|
@ -497,14 +511,14 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
grub_size_t tbl_addr_size;
|
grub_size_t tbl_addr_size;
|
||||||
struct grub_acpi_table_header *table_head;
|
struct grub_acpi_table_header *table_head;
|
||||||
|
|
||||||
exclude = state[0].set ? grub_strdup (state[0].arg) : 0;
|
exclude = state[OPTION_EXCLUDE].set ? grub_strdup (state[OPTION_EXCLUDE].arg) : 0;
|
||||||
if (exclude)
|
if (exclude)
|
||||||
{
|
{
|
||||||
for (ptr = exclude; *ptr; ptr++)
|
for (ptr = exclude; *ptr; ptr++)
|
||||||
*ptr = grub_tolower (*ptr);
|
*ptr = grub_tolower (*ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
load_only = state[1].set ? grub_strdup (state[1].arg) : 0;
|
load_only = state[OPTION_LOAD_ONLY].set ? grub_strdup (state[OPTION_LOAD_ONLY].arg) : 0;
|
||||||
if (load_only)
|
if (load_only)
|
||||||
{
|
{
|
||||||
for (ptr = load_only; *ptr; ptr++)
|
for (ptr = load_only; *ptr; ptr++)
|
||||||
|
@ -623,26 +637,26 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does user specify versions to generate? */
|
/* Does user specify versions to generate? */
|
||||||
if (state[2].set || state[3].set)
|
if (state[OPTION_V1].set || state[OPTION_V2].set)
|
||||||
{
|
{
|
||||||
rev1 = state[2].set;
|
rev1 = state[OPTION_V1].set;
|
||||||
if (state[3].set)
|
if (state[OPTION_V2].set)
|
||||||
rev2 = rev2 ? : 2;
|
rev2 = rev2 ? : 2;
|
||||||
else
|
else
|
||||||
rev2 = 0;
|
rev2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does user override root header information? */
|
/* Does user override root header information? */
|
||||||
if (state[4].set)
|
if (state[OPTION_OEMID].set)
|
||||||
grub_strncpy (root_oemid, state[4].arg, sizeof (root_oemid));
|
grub_strncpy (root_oemid, state[OPTION_OEMID].arg, sizeof (root_oemid));
|
||||||
if (state[5].set)
|
if (state[OPTION_OEMTABLE].set)
|
||||||
grub_strncpy (root_oemtable, state[5].arg, sizeof (root_oemtable));
|
grub_strncpy (root_oemtable, state[OPTION_OEMTABLE].arg, sizeof (root_oemtable));
|
||||||
if (state[6].set)
|
if (state[OPTION_OEMTABLEREV].set)
|
||||||
root_oemrev = grub_strtoul (state[6].arg, 0, 0);
|
root_oemrev = grub_strtoul (state[OPTION_OEMTABLEREV].arg, 0, 0);
|
||||||
if (state[7].set)
|
if (state[OPTION_OEMTABLECREATOR].set)
|
||||||
grub_strncpy (root_creator_id, state[7].arg, sizeof (root_creator_id));
|
grub_strncpy (root_creator_id, state[OPTION_OEMTABLECREATOR].arg, sizeof (root_creator_id));
|
||||||
if (state[8].set)
|
if (state[OPTION_OEMTABLECREATORREV].set)
|
||||||
root_creator_rev = grub_strtoul (state[8].arg, 0, 0);
|
root_creator_rev = grub_strtoul (state[OPTION_OEMTABLECREATORREV].arg, 0, 0);
|
||||||
|
|
||||||
/* Load user tables */
|
/* Load user tables */
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
|
@ -758,7 +772,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
acpi_tables = 0;
|
acpi_tables = 0;
|
||||||
|
|
||||||
#if defined (__i386__) || defined (__x86_64__)
|
#if defined (__i386__) || defined (__x86_64__)
|
||||||
if (! state[9].set)
|
if (! state[OPTION_NO_EBDA].set)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
err = grub_acpi_create_ebda ();
|
err = grub_acpi_create_ebda ();
|
||||||
|
|
|
@ -48,6 +48,22 @@ get_part_uuid (const char *device_name, char **part_uuid)
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return grub_error (grub_errno, N_("cannot open device: %s"), device_name);
|
return grub_error (grub_errno, N_("cannot open device: %s"), device_name);
|
||||||
|
|
||||||
|
if (device->disk == NULL)
|
||||||
|
{
|
||||||
|
grub_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name);
|
||||||
|
*part_uuid = NULL;
|
||||||
|
grub_device_close (device);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->disk->partition == NULL)
|
||||||
|
{
|
||||||
|
grub_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name);
|
||||||
|
*part_uuid = NULL;
|
||||||
|
grub_device_close (device);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
disk = grub_disk_open (device->disk->name);
|
disk = grub_disk_open (device->disk->name);
|
||||||
if (disk == NULL)
|
if (disk == NULL)
|
||||||
{
|
{
|
||||||
|
@ -99,7 +115,7 @@ set_loader_device_part_uuid (void)
|
||||||
|
|
||||||
status = get_part_uuid (device_name, &part_uuid);
|
status = get_part_uuid (device_name, &part_uuid);
|
||||||
|
|
||||||
if (status == GRUB_ERR_NONE)
|
if (status == GRUB_ERR_NONE && part_uuid)
|
||||||
status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid,
|
status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid,
|
||||||
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||||
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
|
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
|
||||||
|
@ -117,4 +133,6 @@ GRUB_MOD_INIT (bli)
|
||||||
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||||
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
|
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
|
||||||
set_loader_device_part_uuid ();
|
set_loader_device_part_uuid ();
|
||||||
|
/* No error here is critical, other than being logged */
|
||||||
|
grub_print_error ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,15 @@ grub_tpm_present (void)
|
||||||
{
|
{
|
||||||
grub_efi_handle_t tpm_handle;
|
grub_efi_handle_t tpm_handle;
|
||||||
grub_efi_uint8_t protocol_version;
|
grub_efi_uint8_t protocol_version;
|
||||||
|
grub_efi_cc_protocol_t *cc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When confidential computing measurement protocol is enabled
|
||||||
|
* we assume the TPM is present.
|
||||||
|
*/
|
||||||
|
cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL);
|
||||||
|
if (cc != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
|
if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -49,6 +49,9 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = grub_arg_list_alloc (ext, argc, args);
|
state = grub_arg_list_alloc (ext, argc, args);
|
||||||
|
if (state == NULL)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
|
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
|
||||||
{
|
{
|
||||||
context.state = state;
|
context.state = state;
|
||||||
|
|
|
@ -306,6 +306,8 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
|
|
||||||
elf = grub_elf_file (file, file->name);
|
elf = grub_elf_file (file, file->name);
|
||||||
|
|
||||||
|
if (elf == NULL)
|
||||||
|
break;
|
||||||
if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)
|
if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)
|
||||||
|| elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB)
|
|| elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <grub/lib/hexdump.h>
|
#include <grub/lib/hexdump.h>
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -51,7 +52,11 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;
|
length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;
|
||||||
|
|
||||||
if (!grub_strcmp (args[0], "(mem)"))
|
if (!grub_strcmp (args[0], "(mem)"))
|
||||||
|
{
|
||||||
|
if (grub_is_lockdown() == GRUB_LOCKDOWN_ENABLED)
|
||||||
|
return grub_error (GRUB_ERR_ACCESS_DENIED, N_("memory reading is disabled in lockdown mode"));
|
||||||
hexdump (skip, (char *) (grub_addr_t) skip, length);
|
hexdump (skip, (char *) (grub_addr_t) skip, length);
|
||||||
|
}
|
||||||
else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
|
else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
|
||||||
{
|
{
|
||||||
grub_disk_t disk;
|
grub_disk_t disk;
|
||||||
|
|
|
@ -104,13 +104,13 @@ static grub_command_t cmd, cmd_clean, cmd_set;
|
||||||
|
|
||||||
GRUB_MOD_INIT(cmostest)
|
GRUB_MOD_INIT(cmostest)
|
||||||
{
|
{
|
||||||
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
|
cmd = grub_register_command_lockdown ("cmostest", grub_cmd_cmostest,
|
||||||
N_("BYTE:BIT"),
|
N_("BYTE:BIT"),
|
||||||
N_("Test bit at BYTE:BIT in CMOS."));
|
N_("Test bit at BYTE:BIT in CMOS."));
|
||||||
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
|
cmd_clean = grub_register_command_lockdown ("cmosclean", grub_cmd_cmosclean,
|
||||||
N_("BYTE:BIT"),
|
N_("BYTE:BIT"),
|
||||||
N_("Clear bit at BYTE:BIT in CMOS."));
|
N_("Clear bit at BYTE:BIT in CMOS."));
|
||||||
cmd_set = grub_register_command ("cmosset", grub_cmd_cmosset,
|
cmd_set = grub_register_command_lockdown ("cmosset", grub_cmd_cmosset,
|
||||||
N_("BYTE:BIT"),
|
N_("BYTE:BIT"),
|
||||||
/* TRANSLATORS: A bit may be either set (1) or clear (0). */
|
/* TRANSLATORS: A bit may be either set (1) or clear (0). */
|
||||||
N_("Set bit at BYTE:BIT in CMOS."));
|
N_("Set bit at BYTE:BIT in CMOS."));
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/i386/cpuid.h>
|
#include <grub/i386/cpuid.h>
|
||||||
#include <grub/i386/rdmsr.h>
|
#include <grub/i386/msr.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE("GPLv3+");
|
GRUB_MOD_LICENSE("GPLv3+");
|
||||||
|
|
||||||
|
@ -42,27 +42,16 @@ static const struct grub_arg_option options[] =
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
||||||
{
|
{
|
||||||
grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
|
grub_err_t err;
|
||||||
|
grub_uint32_t addr;
|
||||||
grub_uint64_t value;
|
grub_uint64_t value;
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
char buf[sizeof("1122334455667788")];
|
char buf[sizeof("1122334455667788")];
|
||||||
|
|
||||||
/*
|
err = grub_cpu_is_msr_supported ();
|
||||||
* The CPUID instruction should be used to determine whether MSRs
|
|
||||||
* are supported. (CPUID.01H:EDX[5] = 1)
|
|
||||||
*/
|
|
||||||
if (! grub_cpu_is_cpuid_supported ())
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
|
if (err != GRUB_ERR_NONE)
|
||||||
|
return grub_error (err, N_("RDMSR is unsupported"));
|
||||||
if (max_cpuid < 1)
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
grub_cpuid (1, a, b, c, features);
|
|
||||||
|
|
||||||
if (!(features & (1 << 5)))
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||||
|
@ -76,7 +65,7 @@ grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
||||||
if (*ptr != '\0')
|
if (*ptr != '\0')
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
||||||
|
|
||||||
value = grub_msr_read (addr);
|
value = grub_rdmsr (addr);
|
||||||
|
|
||||||
if (ctxt->state[0].set)
|
if (ctxt->state[0].set)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <grub/lockdown.h>
|
#include <grub/lockdown.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/i386/cpuid.h>
|
#include <grub/i386/cpuid.h>
|
||||||
#include <grub/i386/wrmsr.h>
|
#include <grub/i386/msr.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE("GPLv3+");
|
GRUB_MOD_LICENSE("GPLv3+");
|
||||||
|
|
||||||
|
@ -36,26 +36,15 @@ static grub_command_t cmd_write;
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char **argv)
|
grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char **argv)
|
||||||
{
|
{
|
||||||
grub_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr;
|
grub_err_t err;
|
||||||
|
grub_uint32_t addr;
|
||||||
grub_uint64_t value;
|
grub_uint64_t value;
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
|
|
||||||
/*
|
err = grub_cpu_is_msr_supported ();
|
||||||
* The CPUID instruction should be used to determine whether MSRs
|
|
||||||
* are supported. (CPUID.01H:EDX[5] = 1)
|
|
||||||
*/
|
|
||||||
if (!grub_cpu_is_cpuid_supported ())
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
|
if (err != GRUB_ERR_NONE)
|
||||||
|
return grub_error (err, N_("WRMSR is unsupported"));
|
||||||
if (max_cpuid < 1)
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
grub_cpuid (1, a, b, c, features);
|
|
||||||
|
|
||||||
if (!(features & (1 << 5)))
|
|
||||||
return grub_error (GRUB_ERR_BUG, N_("unsupported instruction"));
|
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||||
|
@ -77,7 +66,7 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
|
||||||
if (*ptr != '\0')
|
if (*ptr != '\0')
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
||||||
|
|
||||||
grub_msr_write (addr, value);
|
grub_wrmsr (addr, value);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,48 +23,10 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/tpm.h>
|
#include <grub/tpm.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
|
#include <grub/ieee1275/tpm.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
|
||||||
static grub_ieee1275_ihandle_t tpm_ihandle;
|
|
||||||
static grub_uint8_t tpm_version;
|
|
||||||
|
|
||||||
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
|
|
||||||
|
|
||||||
static void
|
|
||||||
tpm_get_tpm_version (void)
|
|
||||||
{
|
|
||||||
grub_ieee1275_phandle_t vtpm;
|
|
||||||
char buffer[20];
|
|
||||||
|
|
||||||
if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
|
|
||||||
!grub_ieee1275_get_property (vtpm, "compatible", buffer,
|
|
||||||
sizeof (buffer), NULL) &&
|
|
||||||
!grub_strcmp (buffer, "IBM,vtpm20"))
|
|
||||||
tpm_version = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
tpm_init (void)
|
|
||||||
{
|
|
||||||
static int init_success = 0;
|
|
||||||
|
|
||||||
if (!init_success)
|
|
||||||
{
|
|
||||||
if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0)
|
|
||||||
{
|
|
||||||
tpm_ihandle = IEEE1275_IHANDLE_INVALID;
|
|
||||||
return GRUB_ERR_UNKNOWN_DEVICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_success = 1;
|
|
||||||
|
|
||||||
tpm_get_tpm_version ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
|
ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
|
||||||
grub_uint32_t eventtype,
|
grub_uint32_t eventtype,
|
||||||
|
@ -90,7 +52,7 @@ ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
|
||||||
|
|
||||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
|
INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
|
||||||
args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
|
args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
|
||||||
args.ihandle = tpm_ihandle;
|
args.ihandle = grub_ieee1275_tpm_ihandle;
|
||||||
args.pcrindex = pcrindex;
|
args.pcrindex = pcrindex;
|
||||||
args.eventtype = eventtype;
|
args.eventtype = eventtype;
|
||||||
args.description = (grub_ieee1275_cell_t) description;
|
args.description = (grub_ieee1275_cell_t) description;
|
||||||
|
@ -138,7 +100,7 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
|
||||||
grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
|
grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
|
||||||
pcr, size, description);
|
pcr, size, description);
|
||||||
|
|
||||||
if (tpm_version == 2)
|
if (grub_ieee1275_tpm_ihandle != GRUB_IEEE1275_IHANDLE_INVALID)
|
||||||
return tpm2_log_event (buf, size, pcr, description);
|
return tpm2_log_event (buf, size, pcr, description);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -151,5 +113,5 @@ grub_tpm_present (void)
|
||||||
* Call tpm_init() "late" rather than from GRUB_MOD_INIT() so that device nodes
|
* Call tpm_init() "late" rather than from GRUB_MOD_INIT() so that device nodes
|
||||||
* can be found.
|
* can be found.
|
||||||
*/
|
*/
|
||||||
return tpm_init() == GRUB_ERR_NONE;
|
return grub_ieee1275_tpm_init() == GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,6 @@ legacy_file (const char *filename)
|
||||||
const char **args = grub_malloc (sizeof (args[0]));
|
const char **args = grub_malloc (sizeof (args[0]));
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
grub_file_close (file);
|
|
||||||
grub_free (suffix);
|
grub_free (suffix);
|
||||||
grub_free (entrysrc);
|
grub_free (entrysrc);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
|
@ -87,37 +87,44 @@ grub_ls_list_devices (int longlist)
|
||||||
struct grub_ls_list_files_ctx
|
struct grub_ls_list_files_ctx
|
||||||
{
|
{
|
||||||
char *dirname;
|
char *dirname;
|
||||||
|
char *filename;
|
||||||
int all;
|
int all;
|
||||||
int human;
|
int human;
|
||||||
|
int longlist;
|
||||||
|
int print_dirhdr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper for grub_ls_list_files. */
|
/* Helper for grub_ls_list_files. */
|
||||||
static int
|
static int
|
||||||
print_files (const char *filename, const struct grub_dirhook_info *info,
|
print_file (const char *filename, const struct grub_dirhook_info *info,
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct grub_ls_list_files_ctx *ctx = data;
|
|
||||||
|
|
||||||
if (ctx->all || filename[0] != '.')
|
|
||||||
grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper for grub_ls_list_files. */
|
|
||||||
static int
|
|
||||||
print_files_long (const char *filename, const struct grub_dirhook_info *info,
|
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
char *pathname = NULL;
|
||||||
struct grub_ls_list_files_ctx *ctx = data;
|
struct grub_ls_list_files_ctx *ctx = data;
|
||||||
|
|
||||||
if ((! ctx->all) && (filename[0] == '.'))
|
if ((! ctx->all) && (filename[0] == '.'))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((ctx->filename != NULL) && (grub_strcmp (filename, ctx->filename) != 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ctx->print_dirhdr)
|
||||||
|
{
|
||||||
|
grub_printf ("%s:\n", ctx->dirname);
|
||||||
|
ctx->print_dirhdr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ctx->longlist)
|
||||||
|
{
|
||||||
|
if (ctx->filename != NULL)
|
||||||
|
grub_xputs (ctx->dirname);
|
||||||
|
grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (! info->dir)
|
if (! info->dir)
|
||||||
{
|
{
|
||||||
grub_file_t file;
|
grub_file_t file;
|
||||||
char *pathname;
|
|
||||||
|
|
||||||
if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/')
|
if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/')
|
||||||
pathname = grub_xasprintf ("%s%s", ctx->dirname, filename);
|
pathname = grub_xasprintf ("%s%s", ctx->dirname, filename);
|
||||||
|
@ -143,7 +150,6 @@ print_files_long (const char *filename, const struct grub_dirhook_info *info,
|
||||||
else
|
else
|
||||||
grub_xputs ("????????????");
|
grub_xputs ("????????????");
|
||||||
|
|
||||||
grub_free (pathname);
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -165,13 +171,22 @@ print_files_long (const char *filename, const struct grub_dirhook_info *info,
|
||||||
datetime.day, datetime.hour,
|
datetime.day, datetime.hour,
|
||||||
datetime.minute, datetime.second);
|
datetime.minute, datetime.second);
|
||||||
}
|
}
|
||||||
grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
|
/*
|
||||||
|
* Only print the full path when listing a file path given as an argument
|
||||||
|
* to ls, i.e. when ctx->filename != NULL. File listings that are printed
|
||||||
|
* due to showing the contents of a directory do not need a full path because
|
||||||
|
* the full path to the directory will have already been printed.
|
||||||
|
*/
|
||||||
|
grub_printf ("%s%s\n", (ctx->filename != NULL) ? pathname : filename,
|
||||||
|
info->dir ? "/" : "");
|
||||||
|
|
||||||
|
grub_free (pathname);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
grub_ls_list_files (char *dirname, int longlist, int all, int human, int dirhdr)
|
||||||
{
|
{
|
||||||
char *device_name;
|
char *device_name;
|
||||||
grub_fs_t fs;
|
grub_fs_t fs;
|
||||||
|
@ -216,42 +231,36 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
||||||
{
|
{
|
||||||
struct grub_ls_list_files_ctx ctx = {
|
struct grub_ls_list_files_ctx ctx = {
|
||||||
.dirname = dirname,
|
.dirname = dirname,
|
||||||
|
.filename = NULL,
|
||||||
.all = all,
|
.all = all,
|
||||||
.human = human
|
.human = human,
|
||||||
|
.longlist = longlist,
|
||||||
|
.print_dirhdr = dirhdr
|
||||||
};
|
};
|
||||||
|
|
||||||
if (longlist)
|
(fs->fs_dir) (dev, path, print_file, &ctx);
|
||||||
(fs->fs_dir) (dev, path, print_files_long, &ctx);
|
|
||||||
else
|
|
||||||
(fs->fs_dir) (dev, path, print_files, &ctx);
|
|
||||||
|
|
||||||
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
|
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
|
||||||
&& path[grub_strlen (path) - 1] != '/')
|
&& path[grub_strlen (path) - 1] != '/')
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Reset errno as it is currently set, but will cause subsequent code
|
||||||
|
* to think there is an error.
|
||||||
|
*/
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
/* PATH might be a regular file. */
|
/* PATH might be a regular file. */
|
||||||
char *p;
|
ctx.print_dirhdr = 0;
|
||||||
grub_file_t file;
|
ctx.filename = grub_strrchr (dirname, '/');
|
||||||
struct grub_dirhook_info info;
|
if (ctx.filename == NULL)
|
||||||
grub_errno = 0;
|
|
||||||
|
|
||||||
file = grub_file_open (dirname, GRUB_FILE_TYPE_GET_SIZE
|
|
||||||
| GRUB_FILE_TYPE_NO_DECOMPRESS);
|
|
||||||
if (! file)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
++(ctx.filename);
|
||||||
|
|
||||||
grub_file_close (file);
|
ctx.dirname = grub_strndup (dirname, ctx.filename - dirname);
|
||||||
|
|
||||||
p = grub_strrchr (dirname, '/') + 1;
|
|
||||||
ctx.dirname = grub_strndup (dirname, p - dirname);
|
|
||||||
if (ctx.dirname == NULL)
|
if (ctx.dirname == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
all = 1;
|
(fs->fs_dir) (dev, ctx.dirname + (path - dirname), print_file, &ctx);
|
||||||
grub_memset (&info, 0, sizeof (info));
|
|
||||||
if (longlist)
|
|
||||||
print_files_long (p, &info, &ctx);
|
|
||||||
else
|
|
||||||
print_files (p, &info, &ctx);
|
|
||||||
|
|
||||||
grub_free (ctx.dirname);
|
grub_free (ctx.dirname);
|
||||||
}
|
}
|
||||||
|
@ -268,7 +277,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
||||||
|
|
||||||
grub_free (device_name);
|
grub_free (device_name);
|
||||||
|
|
||||||
return 0;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -281,10 +290,10 @@ grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
grub_ls_list_devices (state[0].set);
|
grub_ls_list_devices (state[0].set);
|
||||||
else
|
else
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
grub_ls_list_files (args[i], state[0].set, state[2].set,
|
grub_ls_list_files (args[i], state[0].set, state[2].set, state[1].set,
|
||||||
state[1].set);
|
argc > 1);
|
||||||
|
|
||||||
return 0;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_extcmd_t cmd;
|
static grub_extcmd_t cmd;
|
||||||
|
|
|
@ -122,16 +122,19 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
|
||||||
GRUB_MOD_INIT(memrw)
|
GRUB_MOD_INIT(memrw)
|
||||||
{
|
{
|
||||||
cmd_read_byte =
|
cmd_read_byte =
|
||||||
grub_register_extcmd ("read_byte", grub_cmd_read, 0,
|
grub_register_extcmd_lockdown ("read_byte", grub_cmd_read, 0,
|
||||||
N_("ADDR"), N_("Read 8-bit value from ADDR."),
|
N_("ADDR"),
|
||||||
|
N_("Read 8-bit value from ADDR."),
|
||||||
options);
|
options);
|
||||||
cmd_read_word =
|
cmd_read_word =
|
||||||
grub_register_extcmd ("read_word", grub_cmd_read, 0,
|
grub_register_extcmd_lockdown ("read_word", grub_cmd_read, 0,
|
||||||
N_("ADDR"), N_("Read 16-bit value from ADDR."),
|
N_("ADDR"),
|
||||||
|
N_("Read 16-bit value from ADDR."),
|
||||||
options);
|
options);
|
||||||
cmd_read_dword =
|
cmd_read_dword =
|
||||||
grub_register_extcmd ("read_dword", grub_cmd_read, 0,
|
grub_register_extcmd_lockdown ("read_dword", grub_cmd_read, 0,
|
||||||
N_("ADDR"), N_("Read 32-bit value from ADDR."),
|
N_("ADDR"),
|
||||||
|
N_("Read 32-bit value from ADDR."),
|
||||||
options);
|
options);
|
||||||
cmd_write_byte =
|
cmd_write_byte =
|
||||||
grub_register_command_lockdown ("write_byte", grub_cmd_write,
|
grub_register_command_lockdown ("write_byte", grub_cmd_write,
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
#include <grub/cryptodisk.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
/* cat FILE */
|
/* cat FILE */
|
||||||
|
@ -167,7 +171,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
grub_dl_dep_t dep;
|
grub_dl_dep_t dep;
|
||||||
|
|
||||||
grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
|
grub_printf ("%s\t%" PRIuGRUB_UINT64_T "\t\t", mod->name, mod->ref_count);
|
||||||
for (dep = mod->dep; dep; dep = dep->next)
|
for (dep = mod->dep; dep; dep = dep->next)
|
||||||
{
|
{
|
||||||
if (dep != mod->dep)
|
if (dep != mod->dep)
|
||||||
|
@ -187,6 +191,13 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
int argc __attribute__ ((unused)),
|
int argc __attribute__ ((unused)),
|
||||||
char *argv[] __attribute__ ((unused)))
|
char *argv[] __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
/*
|
||||||
|
* The "exit" command is often used to launch the next boot application.
|
||||||
|
* So, erase the secrets.
|
||||||
|
*/
|
||||||
|
grub_cryptodisk_erasesecrets ();
|
||||||
|
#endif
|
||||||
grub_exit ();
|
grub_exit ();
|
||||||
/* Not reached. */
|
/* Not reached. */
|
||||||
}
|
}
|
||||||
|
@ -203,7 +214,7 @@ GRUB_MOD_INIT(minicmd)
|
||||||
grub_register_command ("help", grub_mini_cmd_help,
|
grub_register_command ("help", grub_mini_cmd_help,
|
||||||
0, N_("Show this message."));
|
0, N_("Show this message."));
|
||||||
cmd_dump =
|
cmd_dump =
|
||||||
grub_register_command ("dump", grub_mini_cmd_dump,
|
grub_register_command_lockdown ("dump", grub_mini_cmd_dump,
|
||||||
N_("ADDR [SIZE]"), N_("Show memory contents."));
|
N_("ADDR [SIZE]"), N_("Show memory contents."));
|
||||||
cmd_rmmod =
|
cmd_rmmod =
|
||||||
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
|
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
|
||||||
|
|
|
@ -1010,6 +1010,8 @@ GRUB_MOD_INIT(pgp)
|
||||||
|
|
||||||
GRUB_MOD_FINI(pgp)
|
GRUB_MOD_FINI(pgp)
|
||||||
{
|
{
|
||||||
|
grub_register_variable_hook ("check_signatures", NULL, NULL);
|
||||||
|
grub_env_unset ("check_signatures");
|
||||||
grub_verifier_unregister (&grub_pubkey_verifier);
|
grub_verifier_unregister (&grub_pubkey_verifier);
|
||||||
grub_unregister_extcmd (cmd);
|
grub_unregister_extcmd (cmd);
|
||||||
grub_unregister_extcmd (cmd_trust);
|
grub_unregister_extcmd (cmd_trust);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -37,13 +38,14 @@ static const struct grub_arg_option options[] =
|
||||||
static char *
|
static char *
|
||||||
grub_getline (int silent)
|
grub_getline (int silent)
|
||||||
{
|
{
|
||||||
int i;
|
grub_size_t i;
|
||||||
char *line;
|
char *line;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
int c;
|
int c;
|
||||||
|
grub_size_t alloc_size;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
line = grub_malloc (1 + i + sizeof('\0'));
|
line = grub_malloc (1 + sizeof('\0'));
|
||||||
if (! line)
|
if (! line)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -59,8 +61,17 @@ grub_getline (int silent)
|
||||||
line[i] = (char) c;
|
line[i] = (char) c;
|
||||||
if (!silent)
|
if (!silent)
|
||||||
grub_printf ("%c", c);
|
grub_printf ("%c", c);
|
||||||
i++;
|
if (grub_add (i, 1, &i))
|
||||||
tmp = grub_realloc (line, 1 + i + sizeof('\0'));
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (grub_add (i, 1 + sizeof('\0'), &alloc_size))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tmp = grub_realloc (line, alloc_size);
|
||||||
if (! tmp)
|
if (! tmp)
|
||||||
{
|
{
|
||||||
grub_free (line);
|
grub_free (line);
|
||||||
|
|
|
@ -54,6 +54,41 @@ struct search_ctx
|
||||||
int is_cache;
|
int is_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_unencrypted_disk (grub_disk_t disk)
|
||||||
|
{
|
||||||
|
grub_command_t cmd;
|
||||||
|
char *disk_str;
|
||||||
|
int disk_str_len;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
|
||||||
|
return false; /* This is (crypto) disk. */
|
||||||
|
|
||||||
|
if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
|
||||||
|
{
|
||||||
|
char opt[] = "--quiet";
|
||||||
|
char *args[2];
|
||||||
|
|
||||||
|
cmd = grub_command_find ("cryptocheck");
|
||||||
|
if (cmd == NULL) /* No diskfilter module loaded for some reason. */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
disk_str_len = grub_strlen (disk->name) + 2 + 1;
|
||||||
|
disk_str = grub_malloc (disk_str_len);
|
||||||
|
if (disk_str == NULL) /* Something is wrong, better report as unencrypted. */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
grub_snprintf (disk_str, disk_str_len, "(%s)", disk->name);
|
||||||
|
args[0] = opt;
|
||||||
|
args[1] = disk_str;
|
||||||
|
res = cmd->func (cmd, 2, args);
|
||||||
|
grub_free (disk_str);
|
||||||
|
return (res != GRUB_ERR_NONE) ? true : false; /* GRUB_ERR_NONE for encrypted. */
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper for FUNC_NAME. */
|
/* Helper for FUNC_NAME. */
|
||||||
static int
|
static int
|
||||||
iterate_device (const char *name, void *data)
|
iterate_device (const char *name, void *data)
|
||||||
|
@ -86,6 +121,26 @@ iterate_device (const char *name, void *data)
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Limit to encrypted disks when requested. */
|
||||||
|
if (ctx->flags & SEARCH_FLAGS_CRYPTODISK_ONLY)
|
||||||
|
{
|
||||||
|
grub_device_t dev;
|
||||||
|
|
||||||
|
dev = grub_device_open (name);
|
||||||
|
if (dev == NULL)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (dev->disk == NULL || is_unencrypted_disk (dev->disk) == true)
|
||||||
|
{
|
||||||
|
grub_device_close (dev);
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
grub_device_close (dev);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DO_SEARCH_FS_UUID
|
#ifdef DO_SEARCH_FS_UUID
|
||||||
#define compare_fn grub_strcasecmp
|
#define compare_fn grub_strcasecmp
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
|
||||||
ARG_TYPE_STRING},
|
ARG_TYPE_STRING},
|
||||||
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
|
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
|
||||||
{"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0},
|
{"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0},
|
||||||
|
{"cryptodisk-only", 0, 0, N_("Only probe encrypted disks."), 0, 0},
|
||||||
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
|
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
|
||||||
N_("First try the device HINT. If HINT ends in comma, "
|
N_("First try the device HINT. If HINT ends in comma, "
|
||||||
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
@ -75,6 +76,7 @@ enum options
|
||||||
SEARCH_SET,
|
SEARCH_SET,
|
||||||
SEARCH_NO_FLOPPY,
|
SEARCH_NO_FLOPPY,
|
||||||
SEARCH_EFIDISK_ONLY,
|
SEARCH_EFIDISK_ONLY,
|
||||||
|
SEARCH_CRYPTODISK_ONLY,
|
||||||
SEARCH_HINT,
|
SEARCH_HINT,
|
||||||
SEARCH_HINT_IEEE1275,
|
SEARCH_HINT_IEEE1275,
|
||||||
SEARCH_HINT_BIOS,
|
SEARCH_HINT_BIOS,
|
||||||
|
@ -189,6 +191,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
if (state[SEARCH_EFIDISK_ONLY].set)
|
if (state[SEARCH_EFIDISK_ONLY].set)
|
||||||
flags |= SEARCH_FLAGS_EFIDISK_ONLY;
|
flags |= SEARCH_FLAGS_EFIDISK_ONLY;
|
||||||
|
|
||||||
|
if (state[SEARCH_CRYPTODISK_ONLY].set)
|
||||||
|
flags |= SEARCH_FLAGS_CRYPTODISK_ONLY;
|
||||||
|
|
||||||
if (state[SEARCH_LABEL].set)
|
if (state[SEARCH_LABEL].set)
|
||||||
grub_search_label (id, var, flags, hints, nhints);
|
grub_search_label (id, var, flags, hints, nhints);
|
||||||
else if (state[SEARCH_FS_UUID].set)
|
else if (state[SEARCH_FS_UUID].set)
|
||||||
|
@ -210,7 +215,7 @@ GRUB_MOD_INIT(search)
|
||||||
cmd =
|
cmd =
|
||||||
grub_register_extcmd ("search", grub_cmd_search,
|
grub_register_extcmd ("search", grub_cmd_search,
|
||||||
GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
|
GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
|
||||||
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
|
N_("[-f|-l|-u|-s|-n] [--cryptodisk-only] [--hint HINT [--hint HINT] ...]"
|
||||||
" NAME"),
|
" NAME"),
|
||||||
N_("Search devices by file, filesystem label"
|
N_("Search devices by file, filesystem label"
|
||||||
" or filesystem UUID."
|
" or filesystem UUID."
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
/* Set a limit on recursion to avoid stack overflow. */
|
||||||
|
#define MAX_TEST_RECURSION_DEPTH 100
|
||||||
|
|
||||||
/* A simple implementation for signed numbers. */
|
/* A simple implementation for signed numbers. */
|
||||||
static int
|
static int
|
||||||
grub_strtosl (char *arg, const char ** const end, int base)
|
grub_strtosl (char *arg, const char ** const end, int base)
|
||||||
|
@ -150,7 +153,7 @@ get_fileinfo (char *path, struct test_parse_ctx *ctx)
|
||||||
|
|
||||||
/* Parse a test expression starting from *argn. */
|
/* Parse a test expression starting from *argn. */
|
||||||
static int
|
static int
|
||||||
test_parse (char **args, int *argn, int argc)
|
test_parse (char **args, int *argn, int argc, int *depth)
|
||||||
{
|
{
|
||||||
struct test_parse_ctx ctx = {
|
struct test_parse_ctx ctx = {
|
||||||
.and = 1,
|
.and = 1,
|
||||||
|
@ -387,13 +390,24 @@ test_parse (char **args, int *argn, int argc)
|
||||||
if (grub_strcmp (args[*argn], ")") == 0)
|
if (grub_strcmp (args[*argn], ")") == 0)
|
||||||
{
|
{
|
||||||
(*argn)++;
|
(*argn)++;
|
||||||
|
if (*depth > 0)
|
||||||
|
(*depth)--;
|
||||||
|
|
||||||
return ctx.or || ctx.and;
|
return ctx.or || ctx.and;
|
||||||
}
|
}
|
||||||
/* Recursively invoke if parenthesis. */
|
/* Recursively invoke if parenthesis. */
|
||||||
if (grub_strcmp (args[*argn], "(") == 0)
|
if (grub_strcmp (args[*argn], "(") == 0)
|
||||||
{
|
{
|
||||||
(*argn)++;
|
(*argn)++;
|
||||||
update_val (test_parse (args, argn, argc), &ctx);
|
|
||||||
|
if (++(*depth) > MAX_TEST_RECURSION_DEPTH)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("max recursion depth exceeded"));
|
||||||
|
depth--;
|
||||||
|
return ctx.or || ctx.and;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_val (test_parse (args, argn, argc, depth), &ctx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,11 +442,12 @@ grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc, char **args)
|
int argc, char **args)
|
||||||
{
|
{
|
||||||
int argn = 0;
|
int argn = 0;
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
||||||
argc--;
|
argc--;
|
||||||
|
|
||||||
return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
return test_parse (args, &argn, argc, &depth) ? GRUB_ERR_NONE
|
||||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,16 @@ grub_tpm_verify_init (grub_file_t io,
|
||||||
{
|
{
|
||||||
*context = io->name;
|
*context = io->name;
|
||||||
*flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
|
*flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The loopback image is mapped as a disk allowing it to function like
|
||||||
|
* a block device. However, we measure files read from the block device
|
||||||
|
* not the device itself. For example, we don't measure block devices like
|
||||||
|
* hd0 disk directly. This process is crucial to prevent out-of-memory
|
||||||
|
* errors as loopback images are inherently large.
|
||||||
|
*/
|
||||||
|
if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_LOOPBACK)
|
||||||
|
*flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
127
grub-core/commands/tpm2_key_protector/args.c
Normal file
127
grub-core/commands/tpm2_key_protector/args.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2022 Microsoft Corporation
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
#include "tpm2_args.h"
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs,
|
||||||
|
grub_uint8_t *pcr_count)
|
||||||
|
{
|
||||||
|
char *current_pcr = value;
|
||||||
|
char *next_pcr;
|
||||||
|
const char *pcr_end;
|
||||||
|
grub_uint64_t pcr;
|
||||||
|
grub_uint8_t i;
|
||||||
|
|
||||||
|
if (grub_strlen (value) == 0)
|
||||||
|
return GRUB_ERR_BAD_ARGUMENT;
|
||||||
|
|
||||||
|
*pcr_count = 0;
|
||||||
|
for (i = 0; i < TPM_MAX_PCRS; i++)
|
||||||
|
{
|
||||||
|
next_pcr = grub_strchr (current_pcr, ',');
|
||||||
|
if (next_pcr == current_pcr)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("empty entry in PCR list"));
|
||||||
|
if (next_pcr != NULL)
|
||||||
|
*next_pcr = '\0';
|
||||||
|
|
||||||
|
pcr = grub_strtoul (current_pcr, &pcr_end, 10);
|
||||||
|
if (*current_pcr == '\0' || *pcr_end != '\0')
|
||||||
|
return grub_error (GRUB_ERR_BAD_NUMBER, N_("entry '%s' in PCR list is not a number"), current_pcr);
|
||||||
|
|
||||||
|
if (pcr > TPM_MAX_PCRS - 1)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("entry %llu in PCR list is too large to be a PCR number, PCR numbers range from 0 to %u"), (unsigned long long)pcr, TPM_MAX_PCRS - 1);
|
||||||
|
|
||||||
|
pcrs[i] = (grub_uint8_t) pcr;
|
||||||
|
++(*pcr_count);
|
||||||
|
|
||||||
|
if (next_pcr == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
current_pcr = next_pcr + 1;
|
||||||
|
if (*current_pcr == '\0')
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("trailing comma at the end of PCR list"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == TPM_MAX_PCRS)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("too many PCRs in PCR list, the maximum number of PCRs is %u"), TPM_MAX_PCRS);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2_protector_parse_asymmetric (const char *value,
|
||||||
|
grub_srk_type_t *srk_type)
|
||||||
|
{
|
||||||
|
if (grub_strcasecmp (value, "ECC") == 0 ||
|
||||||
|
grub_strcasecmp (value, "ECC_NIST_P256") == 0)
|
||||||
|
{
|
||||||
|
srk_type->type = TPM_ALG_ECC;
|
||||||
|
srk_type->detail.ecc_curve = TPM_ECC_NIST_P256;
|
||||||
|
}
|
||||||
|
else if (grub_strcasecmp (value, "RSA") == 0 ||
|
||||||
|
grub_strcasecmp (value, "RSA2048") == 0)
|
||||||
|
{
|
||||||
|
srk_type->type = TPM_ALG_RSA;
|
||||||
|
srk_type->detail.rsa_bits = 2048;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid asymmetric key type"), value);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID_t *bank)
|
||||||
|
{
|
||||||
|
if (grub_strcasecmp (value, "SHA1") == 0)
|
||||||
|
*bank = TPM_ALG_SHA1;
|
||||||
|
else if (grub_strcasecmp (value, "SHA256") == 0)
|
||||||
|
*bank = TPM_ALG_SHA256;
|
||||||
|
else if (grub_strcasecmp (value, "SHA384") == 0)
|
||||||
|
*bank = TPM_ALG_SHA384;
|
||||||
|
else if (grub_strcasecmp (value, "SHA512") == 0)
|
||||||
|
*bank = TPM_ALG_SHA512;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid PCR bank"), value);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE_t *handle)
|
||||||
|
{
|
||||||
|
grub_uint64_t num;
|
||||||
|
const char *str_end;
|
||||||
|
|
||||||
|
num = grub_strtoul (value, &str_end, 0);
|
||||||
|
if (*value == '\0' || *str_end != '\0')
|
||||||
|
return grub_error (GRUB_ERR_BAD_NUMBER, N_("TPM handle value '%s' is not a number"), value);
|
||||||
|
|
||||||
|
if (num > GRUB_UINT_MAX)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value %llu is too large to be a TPM handle, TPM handles are unsigned 32-bit integers"), (unsigned long long)num);
|
||||||
|
|
||||||
|
*handle = (TPM_HANDLE_t) num;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
1496
grub-core/commands/tpm2_key_protector/module.c
Normal file
1496
grub-core/commands/tpm2_key_protector/module.c
Normal file
File diff suppressed because it is too large
Load diff
36
grub-core/commands/tpm2_key_protector/tpm2.h
Normal file
36
grub-core/commands/tpm2_key_protector/tpm2.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2022 Microsoft Corporation
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_TPM2_TPM2_HEADER
|
||||||
|
#define GRUB_TPM2_TPM2_HEADER 1
|
||||||
|
|
||||||
|
#include <tss2_types.h>
|
||||||
|
#include <tss2_structs.h>
|
||||||
|
#include <tpm2_cmd.h>
|
||||||
|
|
||||||
|
/* Well-Known Windows SRK handle */
|
||||||
|
#define TPM2_SRK_HANDLE 0x81000001
|
||||||
|
|
||||||
|
struct tpm2_sealed_key {
|
||||||
|
TPM2B_PUBLIC_t public;
|
||||||
|
TPM2B_PRIVATE_t private;
|
||||||
|
};
|
||||||
|
typedef struct tpm2_sealed_key tpm2_sealed_key_t;
|
||||||
|
|
||||||
|
#endif /* ! GRUB_TPM2_TPM2_HEADER */
|
49
grub-core/commands/tpm2_key_protector/tpm2_args.h
Normal file
49
grub-core/commands/tpm2_key_protector/tpm2_args.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2022 Microsoft Corporation
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER
|
||||||
|
#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1
|
||||||
|
|
||||||
|
#include <grub/err.h>
|
||||||
|
|
||||||
|
#include "tpm2.h"
|
||||||
|
|
||||||
|
struct grub_srk_type
|
||||||
|
{
|
||||||
|
TPMI_ALG_PUBLIC_t type;
|
||||||
|
union {
|
||||||
|
TPM_KEY_BITS_t rsa_bits;
|
||||||
|
TPM_ECC_CURVE_t ecc_curve;
|
||||||
|
} detail;
|
||||||
|
};
|
||||||
|
typedef struct grub_srk_type grub_srk_type_t;
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, grub_uint8_t *pcr_count);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2_protector_parse_asymmetric (const char *value, grub_srk_type_t *srk_type);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID_t *bank);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE_t *handle);
|
||||||
|
|
||||||
|
#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */
|
49
grub-core/commands/tpm2_key_protector/tpm2key.asn
Normal file
49
grub-core/commands/tpm2_key_protector/tpm2key.asn
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
--
|
||||||
|
-- GRUB: GRand Unified Bootloader
|
||||||
|
-- Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
--
|
||||||
|
-- GRUB is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- GRUB is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- This file describes TPM 2.0 Key File format for libtasn1.
|
||||||
|
-- To generate tpm2key_asn1_tab.c: asn1Parser tpm2key.asn
|
||||||
|
--
|
||||||
|
TPM2KEY {}
|
||||||
|
DEFINITIONS IMPLICIT TAGS ::=
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
TPMPolicy ::= SEQUENCE {
|
||||||
|
CommandCode [0] EXPLICIT INTEGER,
|
||||||
|
CommandPolicy [1] EXPLICIT OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
TPMAuthPolicy ::= SEQUENCE {
|
||||||
|
Name [0] EXPLICIT UTF8String OPTIONAL,
|
||||||
|
Policy [1] EXPLICIT SEQUENCE OF TPMPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
TPMKey ::= SEQUENCE {
|
||||||
|
type OBJECT IDENTIFIER,
|
||||||
|
emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL,
|
||||||
|
policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL,
|
||||||
|
secret [2] EXPLICIT OCTET STRING OPTIONAL,
|
||||||
|
authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL,
|
||||||
|
description [4] EXPLICIT UTF8String OPTIONAL,
|
||||||
|
rsaParent [5] EXPLICIT BOOLEAN OPTIONAL,
|
||||||
|
parent INTEGER,
|
||||||
|
pubkey OCTET STRING,
|
||||||
|
privkey OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
END
|
499
grub-core/commands/tpm2_key_protector/tpm2key.c
Normal file
499
grub-core/commands/tpm2_key_protector/tpm2key.c
Normal file
|
@ -0,0 +1,499 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2023 SUSE LLC
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/list.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
|
||||||
|
#include <tss2_buffer.h>
|
||||||
|
|
||||||
|
#include "tpm2key.h"
|
||||||
|
|
||||||
|
extern asn1_static_node tpm2key_asn1_tab[];
|
||||||
|
const char *sealed_key_oid = "2.23.133.10.1.5";
|
||||||
|
|
||||||
|
static int
|
||||||
|
asn1_allocate_and_read (asn1_node node, const char *name, void **content, grub_size_t *content_size)
|
||||||
|
{
|
||||||
|
grub_uint8_t *tmpstr = NULL;
|
||||||
|
int tmpstr_size = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (content == NULL)
|
||||||
|
return ASN1_MEM_ERROR;
|
||||||
|
|
||||||
|
ret = asn1_read_value (node, name, NULL, &tmpstr_size);
|
||||||
|
if (ret != ASN1_MEM_ERROR)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
tmpstr = grub_malloc (tmpstr_size);
|
||||||
|
if (tmpstr == NULL)
|
||||||
|
return ASN1_MEM_ERROR;
|
||||||
|
|
||||||
|
ret = asn1_read_value (node, name, tmpstr, &tmpstr_size);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*content = tmpstr;
|
||||||
|
*content_size = tmpstr_size;
|
||||||
|
|
||||||
|
return ASN1_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
asn1_read_uint32 (asn1_node node, const char *name, grub_uint32_t *out)
|
||||||
|
{
|
||||||
|
grub_uint32_t tmp = 0;
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
void *data = NULL;
|
||||||
|
grub_size_t data_size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = asn1_allocate_and_read (node, name, &data, &data_size);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ASN.1 INTEGER is encoded in the following format:
|
||||||
|
*
|
||||||
|
* TAG LENGTH OCTECTS
|
||||||
|
*
|
||||||
|
* The integer TAG is 02 and LENGTH is the number of followed OCTECTS in
|
||||||
|
* big endian. For example:
|
||||||
|
*
|
||||||
|
* 0x1: 02 01 01
|
||||||
|
* 0xabcd: 02 02 ab cd
|
||||||
|
*
|
||||||
|
* To decribe 0x1, it only takes 1 octect, so LENGTH is 0x01 and the
|
||||||
|
* octect is 0x01. On the other hand, 0xabcd requires 2 octects: 'ab" and
|
||||||
|
* 'cd', so LENGTH is 0x02.
|
||||||
|
*
|
||||||
|
* This function only expects a uint32 integer, so it rejects any integer
|
||||||
|
* containing more than 4 octects.
|
||||||
|
*/
|
||||||
|
if (data_size > 4)
|
||||||
|
{
|
||||||
|
ret = ASN1_MEM_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the octects into 'tmp' to make it a big-endian uint32 */
|
||||||
|
ptr = (grub_uint8_t *) &tmp + (4 - data_size);
|
||||||
|
grub_memcpy (ptr, data, data_size);
|
||||||
|
|
||||||
|
/* Convert the big-endian integer to host uint32 */
|
||||||
|
tmp = grub_be_to_cpu32 (tmp);
|
||||||
|
|
||||||
|
*out = tmp;
|
||||||
|
error:
|
||||||
|
if (data)
|
||||||
|
grub_free (data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size)
|
||||||
|
{
|
||||||
|
asn1_node tpm2key;
|
||||||
|
asn1_node tpm2key_asn1 = NULL;
|
||||||
|
void *type_oid = NULL;
|
||||||
|
grub_size_t type_oid_size = 0;
|
||||||
|
void *empty_auth = NULL;
|
||||||
|
grub_size_t empty_auth_size = 0;
|
||||||
|
int tmp_size = 0;
|
||||||
|
int ret;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TPMKey ::= SEQUENCE {
|
||||||
|
* type OBJECT IDENTIFIER,
|
||||||
|
* emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL,
|
||||||
|
* policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL,
|
||||||
|
* secret [2] EXPLICIT OCTET STRING OPTIONAL,
|
||||||
|
* authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL,
|
||||||
|
* description [4] EXPLICIT UTF8String OPTIONAL,
|
||||||
|
* rsaParent [5] EXPLICIT BOOLEAN OPTIONAL,
|
||||||
|
* parent INTEGER,
|
||||||
|
* pubkey OCTET STRING,
|
||||||
|
* privkey OCTET STRING
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
ret = asn1_array2tree (tpm2key_asn1_tab, &tpm2key_asn1, NULL);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to parse TPM2KEY ASN.1 array");
|
||||||
|
|
||||||
|
ret = asn1_create_element (tpm2key_asn1, "TPM2KEY.TPMKey", &tpm2key);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to create TPM2KEY.TPMKey");
|
||||||
|
|
||||||
|
ret = asn1_der_decoding (&tpm2key, data, size, NULL);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to decode TPM2KEY DER");
|
||||||
|
|
||||||
|
/* Check if 'type' is Sealed Key or not */
|
||||||
|
ret = asn1_allocate_and_read (tpm2key, "type", &type_oid, &type_oid_size);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY file");
|
||||||
|
|
||||||
|
if (grub_memcmp (sealed_key_oid, type_oid, type_oid_size) != 0)
|
||||||
|
{
|
||||||
|
err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY file");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'emptyAuth' must be 'TRUE' since we don't support password authorization */
|
||||||
|
ret = asn1_allocate_and_read (tpm2key, "emptyAuth", &empty_auth, &empty_auth_size);
|
||||||
|
if (ret != ASN1_SUCCESS || grub_strncmp ("TRUE", empty_auth, empty_auth_size) != 0)
|
||||||
|
{
|
||||||
|
err = grub_error (GRUB_ERR_BAD_ARGUMENT, "emptyAuth not TRUE");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'secret' should not be in a sealed key */
|
||||||
|
ret = asn1_read_value (tpm2key, "secret", NULL, &tmp_size);
|
||||||
|
if (ret != ASN1_ELEMENT_NOT_FOUND)
|
||||||
|
{
|
||||||
|
err = grub_error (GRUB_ERR_BAD_ARGUMENT, "\"secret\" not allowed for Sealed Key");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*parsed_tpm2key = tpm2key;
|
||||||
|
|
||||||
|
err = GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
grub_free (type_oid);
|
||||||
|
grub_free (empty_auth);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_tpm2key_end_parsing (asn1_node tpm2key)
|
||||||
|
{
|
||||||
|
asn1_delete_structure (&tpm2key);
|
||||||
|
tpm2key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_rsaparent (asn1_node tpm2key, grub_uint8_t *rsaparent)
|
||||||
|
{
|
||||||
|
void *bool_str = NULL;
|
||||||
|
grub_size_t bool_str_size = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (rsaparent == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected");
|
||||||
|
|
||||||
|
if (tpm2key == NULL)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node");
|
||||||
|
|
||||||
|
ret = asn1_allocate_and_read (tpm2key, "rsaParent", &bool_str, &bool_str_size);
|
||||||
|
if (ret == ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
if (grub_strncmp ("TRUE", bool_str, bool_str_size) == 0)
|
||||||
|
*rsaparent = 1;
|
||||||
|
else
|
||||||
|
*rsaparent = 0;
|
||||||
|
}
|
||||||
|
else if (ret == ASN1_ELEMENT_NOT_FOUND)
|
||||||
|
*rsaparent = 0;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve rsaParent");
|
||||||
|
|
||||||
|
grub_free (bool_str);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (parent == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected");
|
||||||
|
|
||||||
|
if (tpm2key == NULL)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node");
|
||||||
|
|
||||||
|
ret = asn1_read_uint32 (tpm2key, "parent", parent);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve parent");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
tpm2key_get_octstring (asn1_node tpm2key, const char *name, void **data, grub_size_t *size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (name == NULL || data == NULL || size == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid parameter(s)");
|
||||||
|
|
||||||
|
if (tpm2key == NULL)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "invalid %s node", name);
|
||||||
|
|
||||||
|
ret = asn1_allocate_and_read (tpm2key, name, data, size);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve %s", name);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size)
|
||||||
|
{
|
||||||
|
return tpm2key_get_octstring (tpm2key, "pubkey", data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size)
|
||||||
|
{
|
||||||
|
return tpm2key_get_octstring (tpm2key, "privkey", data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum and minimum number of elements for 'policy' and 'authPolicy' sequences
|
||||||
|
*
|
||||||
|
* Although there is no limit for the number of sequences elements, we set the upper
|
||||||
|
* bound to 99 to make it easier to implement the code.
|
||||||
|
*
|
||||||
|
* Any 'policy' or 'authPolicy' contains more than 99 commands/policies would become
|
||||||
|
* extremely complex to manage so it is impractical to support such use case.
|
||||||
|
*/
|
||||||
|
#define TPM2KEY_ELEMENTS_MAX 99
|
||||||
|
#define TPM2KEY_ELEMENTS_MIN 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The string to fetch 'Policy' from 'authPolicy':
|
||||||
|
* authPolicy.?XX.Policy
|
||||||
|
*/
|
||||||
|
#define AUTHPOLICY_POL_MAX_STR "authPolicy.?XX.Policy"
|
||||||
|
#define AUTHPOLICY_POL_MAX (sizeof (AUTHPOLICY_POL_MAX_STR))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expected strings for CommandCode and CommandPolicy:
|
||||||
|
* policy.?XX.CommandCode
|
||||||
|
* policy.?XX.CommandPolicy
|
||||||
|
* authPolicy.?XX.Policy.?YY.CommandCode
|
||||||
|
* authPolicy.?XX.Policy.?YY.CommandPolicy
|
||||||
|
*/
|
||||||
|
#define CMD_CODE_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandCode"
|
||||||
|
#define CMD_POL_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandPolicy"
|
||||||
|
#define CMD_CODE_MAX (sizeof (CMD_CODE_MAX_STR))
|
||||||
|
#define CMD_POL_MAX (sizeof (CMD_POL_MAX_STR))
|
||||||
|
|
||||||
|
static int
|
||||||
|
tpm2key_get_policy_seq (asn1_node tpm2key, const char *prefix,
|
||||||
|
tpm2key_policy_t *policy_seq)
|
||||||
|
{
|
||||||
|
tpm2key_policy_t tmp_seq = NULL;
|
||||||
|
tpm2key_policy_t policy = NULL;
|
||||||
|
int policy_n;
|
||||||
|
char cmd_code[CMD_CODE_MAX];
|
||||||
|
char cmd_pol[CMD_POL_MAX];
|
||||||
|
grub_size_t cmd_policy_len;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = asn1_number_of_elements (tpm2key, prefix, &policy_n);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Limit the number of policy commands to two digits (99)
|
||||||
|
* Although there is no upper bound for the number of policy commands,
|
||||||
|
* in practice, it takes one or two policy commands to unseal the key,
|
||||||
|
* so the 99 commands limit is more than enough.
|
||||||
|
*/
|
||||||
|
if (policy_n > TPM2KEY_ELEMENTS_MAX || policy_n < TPM2KEY_ELEMENTS_MIN)
|
||||||
|
return ASN1_VALUE_NOT_VALID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate the policy commands backwards since grub_list_push() prepends
|
||||||
|
* the item into the list.
|
||||||
|
*/
|
||||||
|
for (i = policy_n; i >= 1; i--) {
|
||||||
|
policy = grub_zalloc (sizeof (struct tpm2key_policy));
|
||||||
|
if (policy == NULL)
|
||||||
|
{
|
||||||
|
ret = ASN1_MEM_ALLOC_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
grub_snprintf (cmd_code, CMD_CODE_MAX, "%s.?%d.CommandCode", prefix, i);
|
||||||
|
grub_snprintf (cmd_pol, CMD_POL_MAX, "%s.?%d.CommandPolicy", prefix, i);
|
||||||
|
|
||||||
|
/* CommandCode [0] EXPLICIT INTEGER */
|
||||||
|
ret = asn1_read_uint32 (tpm2key, cmd_code, &policy->cmd_code);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* CommandPolicy [1] EXPLICIT OCTET STRING */
|
||||||
|
ret = tpm2key_get_octstring (tpm2key, cmd_pol, &policy->cmd_policy,
|
||||||
|
&cmd_policy_len);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if (cmd_policy_len > GRUB_TPM2_BUFFER_CAPACITY)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* CommandPolicy is the marshalled parameters for the TPM command so
|
||||||
|
* it should not be larger than the maximum TPM2 buffer.
|
||||||
|
*/
|
||||||
|
ret = ASN1_VALUE_NOT_VALID;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
policy->cmd_policy_len = (grub_uint16_t)cmd_policy_len;
|
||||||
|
|
||||||
|
/* Prepend the policy command into the sequence */
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (policy));
|
||||||
|
}
|
||||||
|
|
||||||
|
*policy_seq = tmp_seq;
|
||||||
|
|
||||||
|
return ASN1_SUCCESS;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (policy != NULL)
|
||||||
|
{
|
||||||
|
grub_free (policy->cmd_policy);
|
||||||
|
grub_free (policy);
|
||||||
|
}
|
||||||
|
grub_tpm2key_free_policy_seq (tmp_seq);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = tpm2key_get_policy_seq (tpm2key, "policy", policy_seq);
|
||||||
|
if (ret == ASN1_ELEMENT_NOT_FOUND)
|
||||||
|
{
|
||||||
|
/* "policy" is optional, so it may not be available */
|
||||||
|
*policy_seq = NULL;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
else if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq)
|
||||||
|
{
|
||||||
|
tpm2key_policy_t policy;
|
||||||
|
tpm2key_policy_t next;
|
||||||
|
|
||||||
|
if (policy_seq == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FOR_LIST_ELEMENTS_SAFE (policy, next, policy_seq)
|
||||||
|
{
|
||||||
|
grub_free (policy->cmd_policy);
|
||||||
|
grub_free (policy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq)
|
||||||
|
{
|
||||||
|
tpm2key_authpolicy_t tmp_seq = NULL;
|
||||||
|
tpm2key_authpolicy_t authpol = NULL;
|
||||||
|
int authpol_n;
|
||||||
|
char authpol_pol[AUTHPOLICY_POL_MAX];
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
ret = asn1_number_of_elements (tpm2key, "authPolicy", &authpol_n);
|
||||||
|
if (ret == ASN1_ELEMENT_NOT_FOUND)
|
||||||
|
{
|
||||||
|
/* "authPolicy" is optional, so it may not be available */
|
||||||
|
*authpol_seq = NULL;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
else if (ret != ASN1_SUCCESS)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve authPolicy");
|
||||||
|
|
||||||
|
/* Limit the number of authPolicy elements to two digits (99) */
|
||||||
|
if (authpol_n > TPM2KEY_ELEMENTS_MAX || authpol_n < TPM2KEY_ELEMENTS_MIN)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid number of authPolicy elements");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate the authPolicy elements backwards since grub_list_push() prepends
|
||||||
|
* the item into the list.
|
||||||
|
*/
|
||||||
|
for (i = authpol_n; i >= 1; i--) {
|
||||||
|
authpol = grub_zalloc (sizeof (struct tpm2key_authpolicy));
|
||||||
|
if (authpol == NULL)
|
||||||
|
{
|
||||||
|
err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate memory for authPolicy");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
grub_snprintf (authpol_pol, AUTHPOLICY_POL_MAX, "authPolicy.?%d.Policy", i);
|
||||||
|
|
||||||
|
ret = tpm2key_get_policy_seq (tpm2key, authpol_pol, &authpol->policy_seq);
|
||||||
|
if (ret != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
err = grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy from authPolicy");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepend the authPolicy element into the sequence */
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (authpol));
|
||||||
|
}
|
||||||
|
|
||||||
|
*authpol_seq = tmp_seq;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (authpol != NULL)
|
||||||
|
{
|
||||||
|
grub_tpm2key_free_policy_seq (authpol->policy_seq);
|
||||||
|
grub_free (authpol);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_tpm2key_free_authpolicy_seq (tmp_seq);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq)
|
||||||
|
{
|
||||||
|
tpm2key_authpolicy_t authpol;
|
||||||
|
tpm2key_authpolicy_t next;
|
||||||
|
|
||||||
|
if (authpol_seq == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FOR_LIST_ELEMENTS_SAFE (authpol, next, authpol_seq)
|
||||||
|
{
|
||||||
|
grub_tpm2key_free_policy_seq (authpol->policy_seq);
|
||||||
|
grub_free (authpol);
|
||||||
|
}
|
||||||
|
}
|
87
grub-core/commands/tpm2_key_protector/tpm2key.h
Normal file
87
grub-core/commands/tpm2_key_protector/tpm2key.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2023 SUSE LLC
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_TPM2_TPM2KEY_HEADER
|
||||||
|
#define GRUB_TPM2_TPM2KEY_HEADER 1
|
||||||
|
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <libtasn1.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TPMPolicy ::= SEQUENCE {
|
||||||
|
* CommandCode [0] EXPLICIT INTEGER,
|
||||||
|
* CommandPolicy [1] EXPLICIT OCTET STRING
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
struct tpm2key_policy {
|
||||||
|
struct tpm2key_policy *next;
|
||||||
|
struct tpm2key_policy **prev;
|
||||||
|
grub_uint32_t cmd_code;
|
||||||
|
void *cmd_policy;
|
||||||
|
grub_uint16_t cmd_policy_len;
|
||||||
|
};
|
||||||
|
typedef struct tpm2key_policy *tpm2key_policy_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TPMAuthPolicy ::= SEQUENCE {
|
||||||
|
* Name [0] EXPLICIT UTF8String OPTIONAL,
|
||||||
|
* Policy [1] EXPLICIT SEQUENCE OF TPMPolicy
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Name is not a necessary part to unseal the key. Ignore it.
|
||||||
|
*/
|
||||||
|
struct tpm2key_authpolicy {
|
||||||
|
struct tpm2key_authpolicy *next;
|
||||||
|
struct tpm2key_authpolicy **prev;
|
||||||
|
/* char *name; */
|
||||||
|
tpm2key_policy_t policy_seq;
|
||||||
|
};
|
||||||
|
typedef struct tpm2key_authpolicy *tpm2key_authpolicy_t;
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
grub_tpm2key_end_parsing (asn1_node tpm2key);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_rsaparent (asn1_node tpm2key, grub_uint8_t *rsaparent);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq);
|
||||||
|
|
||||||
|
extern grub_err_t
|
||||||
|
grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq);
|
||||||
|
|
||||||
|
#endif /* GRUB_TPM2_TPM2KEY_HEADER */
|
63
grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c
Normal file
63
grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is generated by 'asn1Parser tpm2key.asn' and the '#include'
|
||||||
|
* headers are replaced with the ones in grub2.
|
||||||
|
* - 'grub/mm.h' for the definition of 'NULL'
|
||||||
|
* - 'libtasn1.h' for the definition of 'asn1_static_node'
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <libtasn1.h>
|
||||||
|
|
||||||
|
const asn1_static_node tpm2key_asn1_tab[] = {
|
||||||
|
{ "TPM2KEY", 536875024, NULL },
|
||||||
|
{ NULL, 1073741836, NULL },
|
||||||
|
{ "TPMPolicy", 1610612741, NULL },
|
||||||
|
{ "CommandCode", 1610620931, NULL },
|
||||||
|
{ NULL, 2056, "0"},
|
||||||
|
{ "CommandPolicy", 536879111, NULL },
|
||||||
|
{ NULL, 2056, "1"},
|
||||||
|
{ "TPMAuthPolicy", 1610612741, NULL },
|
||||||
|
{ "Name", 1610637346, NULL },
|
||||||
|
{ NULL, 2056, "0"},
|
||||||
|
{ "Policy", 536879115, NULL },
|
||||||
|
{ NULL, 1073743880, "1"},
|
||||||
|
{ NULL, 2, "TPMPolicy"},
|
||||||
|
{ "TPMKey", 536870917, NULL },
|
||||||
|
{ "type", 1073741836, NULL },
|
||||||
|
{ "emptyAuth", 1610637316, NULL },
|
||||||
|
{ NULL, 2056, "0"},
|
||||||
|
{ "policy", 1610637323, NULL },
|
||||||
|
{ NULL, 1073743880, "1"},
|
||||||
|
{ NULL, 2, "TPMPolicy"},
|
||||||
|
{ "secret", 1610637319, NULL },
|
||||||
|
{ NULL, 2056, "2"},
|
||||||
|
{ "authPolicy", 1610637323, NULL },
|
||||||
|
{ NULL, 1073743880, "3"},
|
||||||
|
{ NULL, 2, "TPMAuthPolicy"},
|
||||||
|
{ "description", 1610637346, NULL },
|
||||||
|
{ NULL, 2056, "4"},
|
||||||
|
{ "rsaParent", 1610637316, NULL },
|
||||||
|
{ NULL, 2056, "5"},
|
||||||
|
{ "parent", 1073741827, NULL },
|
||||||
|
{ "pubkey", 1073741831, NULL },
|
||||||
|
{ "privkey", 7, NULL },
|
||||||
|
{ NULL, 0, NULL }
|
||||||
|
};
|
|
@ -152,8 +152,7 @@ struct grub_ahci_device
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||||
struct grub_disk_ata_pass_through_parms *parms,
|
struct grub_disk_ata_pass_through_parms *parms, int reset);
|
||||||
int spinup, int reset);
|
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -573,7 +572,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||||
/* struct grub_disk_ata_pass_through_parms parms2;
|
/* struct grub_disk_ata_pass_through_parms parms2;
|
||||||
grub_memset (&parms2, 0, sizeof (parms2));
|
grub_memset (&parms2, 0, sizeof (parms2));
|
||||||
parms2.taskfile.cmd = 8;
|
parms2.taskfile.cmd = 8;
|
||||||
grub_ahci_readwrite_real (dev, &parms2, 1, 1);*/
|
grub_ahci_readwrite_real (dev, &parms2, 1);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
endtime = grub_get_time_ms () + 32000;
|
endtime = grub_get_time_ms () + 32000;
|
||||||
|
@ -908,15 +907,14 @@ grub_ahci_reset_port (struct grub_ahci_device *dev, int force)
|
||||||
dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
|
dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
|
||||||
grub_memset (&parms2, 0, sizeof (parms2));
|
grub_memset (&parms2, 0, sizeof (parms2));
|
||||||
parms2.taskfile.cmd = 8;
|
parms2.taskfile.cmd = 8;
|
||||||
return grub_ahci_readwrite_real (dev, &parms2, 1, 1);
|
return grub_ahci_readwrite_real (dev, &parms2, 1);
|
||||||
}
|
}
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||||
struct grub_disk_ata_pass_through_parms *parms,
|
struct grub_disk_ata_pass_through_parms *parms, int reset)
|
||||||
int spinup, int reset)
|
|
||||||
{
|
{
|
||||||
struct grub_pci_dma_chunk *bufc;
|
struct grub_pci_dma_chunk *bufc;
|
||||||
grub_uint64_t endtime;
|
grub_uint64_t endtime;
|
||||||
|
@ -1038,7 +1036,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||||
dev->hba->ports[dev->port].task_file_data);
|
dev->hba->ports[dev->port].task_file_data);
|
||||||
|
|
||||||
endtime = grub_get_time_ms () + (spinup ? 20000 : 20000);
|
endtime = grub_get_time_ms () + 20000;
|
||||||
while ((dev->hba->ports[dev->port].command_issue & 1))
|
while ((dev->hba->ports[dev->port].command_issue & 1))
|
||||||
if (grub_get_time_ms () > endtime ||
|
if (grub_get_time_ms () > endtime ||
|
||||||
(dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK))
|
(dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK))
|
||||||
|
@ -1097,9 +1095,9 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ahci_readwrite (grub_ata_t disk,
|
grub_ahci_readwrite (grub_ata_t disk,
|
||||||
struct grub_disk_ata_pass_through_parms *parms,
|
struct grub_disk_ata_pass_through_parms *parms,
|
||||||
int spinup)
|
int spinup __attribute__((__unused__)))
|
||||||
{
|
{
|
||||||
return grub_ahci_readwrite_real (disk->data, parms, spinup, 0);
|
return grub_ahci_readwrite_real (disk->data, parms, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
|
|
@ -112,10 +112,10 @@ grub_ata_identify (struct grub_ata *dev)
|
||||||
return grub_atapi_identify (dev);
|
return grub_atapi_identify (dev);
|
||||||
|
|
||||||
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||||
|
if (info64 == NULL)
|
||||||
|
return grub_errno;
|
||||||
info32 = (grub_uint32_t *) info64;
|
info32 = (grub_uint32_t *) info64;
|
||||||
info16 = (grub_uint16_t *) info64;
|
info16 = (grub_uint16_t *) info64;
|
||||||
if (! info16)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
grub_memset (&parms, 0, sizeof (parms));
|
grub_memset (&parms, 0, sizeof (parms));
|
||||||
parms.buffer = info16;
|
parms.buffer = info16;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/cryptodisk.h>
|
#include <grub/cryptodisk.h>
|
||||||
|
#include <grub/env.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/procfs.h>
|
#include <grub/procfs.h>
|
||||||
#include <grub/partition.h>
|
#include <grub/partition.h>
|
||||||
|
#include <grub/key_protector.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
#include <grub/emu/hostdisk.h>
|
#include <grub/emu/hostdisk.h>
|
||||||
|
@ -44,7 +47,8 @@ enum
|
||||||
OPTION_KEYFILE,
|
OPTION_KEYFILE,
|
||||||
OPTION_KEYFILE_OFFSET,
|
OPTION_KEYFILE_OFFSET,
|
||||||
OPTION_KEYFILE_SIZE,
|
OPTION_KEYFILE_SIZE,
|
||||||
OPTION_HEADER
|
OPTION_HEADER,
|
||||||
|
OPTION_PROTECTOR
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct grub_arg_option options[] =
|
static const struct grub_arg_option options[] =
|
||||||
|
@ -58,6 +62,8 @@ static const struct grub_arg_option options[] =
|
||||||
{"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
|
{"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
|
||||||
{"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
|
{"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
|
||||||
{"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
|
{"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
|
||||||
|
{"protector", 'P', GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1061,6 +1067,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||||
grub_err_t ret = GRUB_ERR_NONE;
|
grub_err_t ret = GRUB_ERR_NONE;
|
||||||
grub_cryptodisk_t dev;
|
grub_cryptodisk_t dev;
|
||||||
grub_cryptodisk_dev_t cr;
|
grub_cryptodisk_dev_t cr;
|
||||||
|
int i;
|
||||||
struct cryptodisk_read_hook_ctx read_hook_data = {0};
|
struct cryptodisk_read_hook_ctx read_hook_data = {0};
|
||||||
int askpass = 0;
|
int askpass = 0;
|
||||||
char *part = NULL;
|
char *part = NULL;
|
||||||
|
@ -1113,11 +1120,140 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||||
goto error_no_close;
|
goto error_no_close;
|
||||||
if (!dev)
|
if (!dev)
|
||||||
continue;
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cargs->key_len)
|
if (dev == NULL)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_MODULE,
|
||||||
|
"no cryptodisk module can handle this device");
|
||||||
|
goto error_no_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cargs->protectors)
|
||||||
|
{
|
||||||
|
for (i = 0; cargs->protectors[i]; i++)
|
||||||
|
{
|
||||||
|
if (cargs->key_cache[i].invalid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cargs->key_cache[i].key == NULL)
|
||||||
|
{
|
||||||
|
ret = grub_key_protector_recover_key (cargs->protectors[i],
|
||||||
|
&cargs->key_cache[i].key,
|
||||||
|
&cargs->key_cache[i].key_len);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("cryptodisk",
|
||||||
|
"failed to recover a key from key protector "
|
||||||
|
"%s, will not try it again for any other "
|
||||||
|
"disks, if any, during this invocation of "
|
||||||
|
"cryptomount\n",
|
||||||
|
cargs->protectors[i]);
|
||||||
|
|
||||||
|
cargs->key_cache[i].invalid = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cargs->key_data = cargs->key_cache[i].key;
|
||||||
|
cargs->key_len = cargs->key_cache[i].key_len;
|
||||||
|
|
||||||
|
ret = cr->recover_key (source, dev, cargs);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
/* Reset key data to trigger the passphrase prompt later */
|
||||||
|
cargs->key_data = NULL;
|
||||||
|
cargs->key_len = 0;
|
||||||
|
|
||||||
|
part = grub_partition_get_name (source->partition);
|
||||||
|
grub_dprintf ("cryptodisk",
|
||||||
|
"recovered a key from key protector %s but it "
|
||||||
|
"failed to unlock %s%s%s (%s)\n",
|
||||||
|
cargs->protectors[i], source->name,
|
||||||
|
source->partition != NULL ? "," : "",
|
||||||
|
part != NULL ? part : N_("UNKNOWN"), dev->uuid);
|
||||||
|
grub_free (part);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = grub_cryptodisk_insert (dev, name, source);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
goto error;
|
||||||
|
#ifndef GRUB_UTIL
|
||||||
|
grub_cli_set_auth_needed ();
|
||||||
|
#endif
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
part = grub_partition_get_name (source->partition);
|
||||||
|
grub_error (GRUB_ERR_ACCESS_DENIED,
|
||||||
|
N_("no key protector provided a usable key for %s%s%s (%s)"),
|
||||||
|
source->name, source->partition != NULL ? "," : "",
|
||||||
|
part != NULL ? part : N_("UNKNOWN"), dev->uuid);
|
||||||
|
grub_free (part);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cargs->key_len)
|
||||||
|
{
|
||||||
|
ret = cr->recover_key (source, dev, cargs);
|
||||||
|
if (ret != GRUB_ERR_NONE)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Get the passphrase from the user, if no key data. */
|
/* Get the passphrase from the user, if no key data. */
|
||||||
|
unsigned long tries = 3;
|
||||||
|
const char *tries_env;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the error from key protectors and clear grub_errno.
|
||||||
|
*
|
||||||
|
* Since '--protector' cannot coexist with '--password' and
|
||||||
|
* '--key-file', in case key protectors fail, only
|
||||||
|
* "cargs->key_len == 0" is expected, so cryptomount falls back
|
||||||
|
* here to request the passphrase.
|
||||||
|
*
|
||||||
|
* To avoid the error from key protectors stops the further code,
|
||||||
|
* print the error to notify the user why key protectors fail and
|
||||||
|
* clear grub_errno to have a fresh start.
|
||||||
|
*/
|
||||||
|
if (grub_errno != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
askpass = 1;
|
askpass = 1;
|
||||||
|
cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||||
|
if (cargs->key_data == NULL)
|
||||||
|
goto error_no_close;
|
||||||
|
|
||||||
|
tries_env = grub_env_get ("cryptodisk_passphrase_tries");
|
||||||
|
if (tries_env != NULL && tries_env[0] != '\0')
|
||||||
|
{
|
||||||
|
unsigned long tries_env_val;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
tries_env_val = grub_strtoul (tries_env, &p, 0);
|
||||||
|
if (*p == '\0' && tries_env_val != ~0UL)
|
||||||
|
tries = tries_env_val;
|
||||||
|
else
|
||||||
|
grub_printf_ (N_("Invalid cryptodisk_passphrase_tries value `%s'. Defaulting to %lu.\n"),
|
||||||
|
tries_env,
|
||||||
|
tries);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; tries > 0; tries--)
|
||||||
|
{
|
||||||
part = grub_partition_get_name (source->partition);
|
part = grub_partition_get_name (source->partition);
|
||||||
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||||
source->partition != NULL ? "," : "",
|
source->partition != NULL ? "," : "",
|
||||||
|
@ -1125,30 +1261,35 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||||
dev->uuid);
|
dev->uuid);
|
||||||
grub_free (part);
|
grub_free (part);
|
||||||
|
|
||||||
cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
|
||||||
if (cargs->key_data == NULL)
|
|
||||||
goto error_no_close;
|
|
||||||
|
|
||||||
if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
|
grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
cargs->key_len = grub_strlen ((char *) cargs->key_data);
|
cargs->key_len = grub_strlen ((char *) cargs->key_data);
|
||||||
}
|
|
||||||
|
|
||||||
ret = cr->recover_key (source, dev, cargs);
|
ret = cr->recover_key (source, dev, cargs);
|
||||||
if (ret != GRUB_ERR_NONE)
|
if (ret == GRUB_ERR_NONE)
|
||||||
|
break;
|
||||||
|
if (ret != GRUB_ERR_ACCESS_DENIED || tries == 1)
|
||||||
goto error;
|
goto error;
|
||||||
|
grub_puts_ (N_("Invalid passphrase."));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since recover_key() calls a function that returns grub_errno,
|
||||||
|
* a leftover error value from a previously rejected passphrase
|
||||||
|
* will trigger a phantom failure. We therefore clear it before
|
||||||
|
* trying a new passphrase.
|
||||||
|
*/
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = grub_cryptodisk_insert (dev, name, source);
|
ret = grub_cryptodisk_insert (dev, name, source);
|
||||||
if (ret != GRUB_ERR_NONE)
|
if (ret != GRUB_ERR_NONE)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
cryptodisk_close (dev);
|
cryptodisk_close (dev);
|
||||||
|
@ -1161,6 +1302,7 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||||||
|
|
||||||
if (askpass)
|
if (askpass)
|
||||||
{
|
{
|
||||||
|
grub_memset (cargs->key_data, 0, cargs->key_len);
|
||||||
cargs->key_len = 0;
|
cargs->key_len = 0;
|
||||||
grub_free (cargs->key_data);
|
grub_free (cargs->key_data);
|
||||||
}
|
}
|
||||||
|
@ -1259,6 +1401,24 @@ grub_cryptodisk_scan_device (const char *name,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (cargs->key_cache == NULL || cargs->protectors == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; cargs->protectors[i]; i++)
|
||||||
|
{
|
||||||
|
if (cargs->key_cache[i].key)
|
||||||
|
grub_memset (cargs->key_cache[i].key, 0, cargs->key_cache[i].key_len);
|
||||||
|
grub_free (cargs->key_cache[i].key);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_free (cargs->key_cache);
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
|
@ -1271,6 +1431,14 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
if (grub_cryptodisk_list == NULL)
|
if (grub_cryptodisk_list == NULL)
|
||||||
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
|
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
|
||||||
|
|
||||||
|
if (state[OPTION_PASSWORD].set && state[OPTION_PROTECTOR].set) /* password and key protector */
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
"a password and a key protector cannot both be set");
|
||||||
|
|
||||||
|
if (state[OPTION_KEYFILE].set && state[OPTION_PROTECTOR].set) /* key file and key protector */
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
"a key file and a key protector cannot both be set");
|
||||||
|
|
||||||
if (state[OPTION_PASSWORD].set) /* password */
|
if (state[OPTION_PASSWORD].set) /* password */
|
||||||
{
|
{
|
||||||
cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
|
cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
|
||||||
|
@ -1320,9 +1488,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
|
|
||||||
if (keyfile_offset > keyfile->size)
|
if (keyfile_offset > keyfile->size)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
N_("Keyfile offset, %llu, is greater than"
|
N_("Keyfile offset, %llu, is greater than "
|
||||||
"keyfile size, %" PRIuGRUB_UINT64_T),
|
"keyfile size, %llu"),
|
||||||
keyfile_offset, keyfile->size);
|
keyfile_offset, (unsigned long long) keyfile->size);
|
||||||
|
|
||||||
if (grub_file_seek (keyfile, (grub_off_t) keyfile_offset) == (grub_off_t) -1)
|
if (grub_file_seek (keyfile, (grub_off_t) keyfile_offset) == (grub_off_t) -1)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -1363,6 +1531,15 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state[OPTION_PROTECTOR].set) /* key protector(s) */
|
||||||
|
{
|
||||||
|
cargs.key_cache = grub_calloc (state[OPTION_PROTECTOR].set, sizeof (*cargs.key_cache));
|
||||||
|
if (cargs.key_cache == NULL)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
"no memory for key protector key cache");
|
||||||
|
cargs.protectors = state[OPTION_PROTECTOR].args;
|
||||||
|
}
|
||||||
|
|
||||||
if (state[OPTION_UUID].set) /* uuid */
|
if (state[OPTION_UUID].set) /* uuid */
|
||||||
{
|
{
|
||||||
int found_uuid;
|
int found_uuid;
|
||||||
|
@ -1371,6 +1548,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
dev = grub_cryptodisk_get_by_uuid (args[0]);
|
dev = grub_cryptodisk_get_by_uuid (args[0]);
|
||||||
if (dev)
|
if (dev)
|
||||||
{
|
{
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
grub_dprintf ("cryptodisk",
|
grub_dprintf ("cryptodisk",
|
||||||
"already mounted as crypto%lu\n", dev->id);
|
"already mounted as crypto%lu\n", dev->id);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -1379,6 +1557,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
cargs.check_boot = state[OPTION_BOOT].set;
|
cargs.check_boot = state[OPTION_BOOT].set;
|
||||||
cargs.search_uuid = args[0];
|
cargs.search_uuid = args[0];
|
||||||
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
|
|
||||||
if (found_uuid)
|
if (found_uuid)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -1398,6 +1577,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
cargs.check_boot = state[OPTION_BOOT].set;
|
cargs.check_boot = state[OPTION_BOOT].set;
|
||||||
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1421,6 +1601,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
disk = grub_disk_open (diskname);
|
disk = grub_disk_open (diskname);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
{
|
{
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
if (disklast)
|
if (disklast)
|
||||||
*disklast = ')';
|
*disklast = ')';
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -1431,12 +1612,14 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
|
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
|
||||||
grub_disk_close (disk);
|
grub_disk_close (disk);
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
if (disklast)
|
if (disklast)
|
||||||
*disklast = ')';
|
*disklast = ')';
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
|
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
|
||||||
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||||||
|
|
||||||
grub_disk_close (disk);
|
grub_disk_close (disk);
|
||||||
if (disklast)
|
if (disklast)
|
||||||
|
@ -1473,7 +1656,7 @@ static char *
|
||||||
luks_script_get (grub_size_t *sz)
|
luks_script_get (grub_size_t *sz)
|
||||||
{
|
{
|
||||||
grub_cryptodisk_t i;
|
grub_cryptodisk_t i;
|
||||||
grub_size_t size = 0;
|
grub_size_t size = 0, mul;
|
||||||
char *ptr, *ret;
|
char *ptr, *ret;
|
||||||
|
|
||||||
*sz = 0;
|
*sz = 0;
|
||||||
|
@ -1482,10 +1665,6 @@ luks_script_get (grub_size_t *sz)
|
||||||
if (grub_strcmp (i->modname, "luks") == 0 ||
|
if (grub_strcmp (i->modname, "luks") == 0 ||
|
||||||
grub_strcmp (i->modname, "luks2") == 0)
|
grub_strcmp (i->modname, "luks2") == 0)
|
||||||
{
|
{
|
||||||
size += grub_strlen (i->modname);
|
|
||||||
size += sizeof ("_mount");
|
|
||||||
size += grub_strlen (i->uuid);
|
|
||||||
size += grub_strlen (i->cipher->cipher->name);
|
|
||||||
/*
|
/*
|
||||||
* Add space in the line for (in order) spaces, cipher mode, cipher IV
|
* Add space in the line for (in order) spaces, cipher mode, cipher IV
|
||||||
* mode, sector offset, sector size and the trailing newline. This is
|
* mode, sector offset, sector size and the trailing newline. This is
|
||||||
|
@ -1493,14 +1672,35 @@ luks_script_get (grub_size_t *sz)
|
||||||
* in an earlier version of this code that are unaccounted for. It is
|
* in an earlier version of this code that are unaccounted for. It is
|
||||||
* left in the calculations in case it is needed. At worst, its short-
|
* left in the calculations in case it is needed. At worst, its short-
|
||||||
* lived wasted space.
|
* lived wasted space.
|
||||||
|
*
|
||||||
|
* 60 = 5 + 5 + 8 + 20 + 6 + 1 + 15
|
||||||
*/
|
*/
|
||||||
size += 5 + 5 + 8 + 20 + 6 + 1 + 15;
|
if (grub_add (size, grub_strlen (i->modname), &size) ||
|
||||||
|
grub_add (size, sizeof ("_mount") + 60, &size) ||
|
||||||
|
grub_add (size, grub_strlen (i->uuid), &size) ||
|
||||||
|
grub_add (size, grub_strlen (i->cipher->cipher->name), &size) ||
|
||||||
|
grub_mul (i->keysize, 2, &mul) ||
|
||||||
|
grub_add (size, mul, &size))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (i->essiv_hash)
|
if (i->essiv_hash)
|
||||||
size += grub_strlen (i->essiv_hash->name);
|
{
|
||||||
size += i->keysize * 2;
|
if (grub_add (size, grub_strlen (i->essiv_hash->name), &size))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grub_add (size, 1, &size))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = grub_malloc (size + 1);
|
ret = grub_malloc (size);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1576,6 +1776,114 @@ luks_script_get (grub_size_t *sz)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
grub_err_t
|
||||||
|
grub_cryptodisk_challenge_password (void)
|
||||||
|
{
|
||||||
|
grub_cryptodisk_t cr_dev;
|
||||||
|
|
||||||
|
for (cr_dev = cryptodisk_list; cr_dev != NULL; cr_dev = cr_dev->next)
|
||||||
|
{
|
||||||
|
grub_cryptodisk_dev_t cr;
|
||||||
|
grub_disk_t source = NULL;
|
||||||
|
grub_err_t ret = GRUB_ERR_NONE;
|
||||||
|
grub_cryptodisk_t dev = NULL;
|
||||||
|
char *part = NULL;
|
||||||
|
struct grub_cryptomount_args cargs = {0};
|
||||||
|
|
||||||
|
cargs.check_boot = 0;
|
||||||
|
cargs.search_uuid = cr_dev->uuid;
|
||||||
|
|
||||||
|
source = grub_disk_open (cr_dev->source);
|
||||||
|
|
||||||
|
if (source == NULL)
|
||||||
|
{
|
||||||
|
ret = grub_errno;
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_CRYPTODISK_DEVS (cr)
|
||||||
|
{
|
||||||
|
dev = cr->scan (source, &cargs);
|
||||||
|
if (grub_errno)
|
||||||
|
{
|
||||||
|
ret = grub_errno;
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
if (dev == NULL)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev == NULL)
|
||||||
|
{
|
||||||
|
ret = grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = grub_partition_get_name (source->partition);
|
||||||
|
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||||
|
source->partition != NULL ? "," : "",
|
||||||
|
part != NULL ? part : N_("UNKNOWN"), cr_dev->uuid);
|
||||||
|
grub_free (part);
|
||||||
|
|
||||||
|
cargs.key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
|
||||||
|
if (cargs.key_data == NULL)
|
||||||
|
{
|
||||||
|
ret = grub_errno;
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grub_password_get ((char *) cargs.key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
|
||||||
|
{
|
||||||
|
ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
cargs.key_len = grub_strlen ((char *) cargs.key_data);
|
||||||
|
ret = cr->recover_key (source, dev, &cargs);
|
||||||
|
|
||||||
|
error_out:
|
||||||
|
grub_disk_close (source);
|
||||||
|
if (dev != NULL)
|
||||||
|
cryptodisk_close (dev);
|
||||||
|
if (cargs.key_data)
|
||||||
|
{
|
||||||
|
grub_memset (cargs.key_data, 0, cargs.key_len);
|
||||||
|
grub_free (cargs.key_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_cryptodisk_erasesecrets (void)
|
||||||
|
{
|
||||||
|
grub_cryptodisk_t i;
|
||||||
|
grub_uint8_t *buf;
|
||||||
|
|
||||||
|
buf = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN);
|
||||||
|
if (buf == NULL)
|
||||||
|
grub_fatal ("grub_cryptodisk_erasesecrets: cannot allocate memory");
|
||||||
|
|
||||||
|
for (i = cryptodisk_list; i != NULL; i = i->next)
|
||||||
|
if (grub_cryptodisk_setkey (i, buf, i->keysize))
|
||||||
|
grub_fatal ("grub_cryptodisk_erasesecrets: cannot erase secrets for %s", i->source);
|
||||||
|
else
|
||||||
|
grub_printf ("Erased crypto secrets for %s\n", i->source);
|
||||||
|
/*
|
||||||
|
* Unfortunately, there is no way to "force unmount" a given disk, it may
|
||||||
|
* have mounted "child" disks as well, e.g., an LVM volume. So, this
|
||||||
|
* function MUST be called when there is no way back, e.g., when exiting.
|
||||||
|
* Otherwise, subsequent read calls for a cryptodisk will return garbage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
grub_free (buf);
|
||||||
|
}
|
||||||
|
#endif /* GRUB_MACHINE_EFI */
|
||||||
|
|
||||||
struct grub_procfs_entry luks_script =
|
struct grub_procfs_entry luks_script =
|
||||||
{
|
{
|
||||||
.name = "luks_script",
|
.name = "luks_script",
|
||||||
|
@ -1590,6 +1898,7 @@ GRUB_MOD_INIT (cryptodisk)
|
||||||
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
||||||
N_("[ [-p password] | [-k keyfile"
|
N_("[ [-p password] | [-k keyfile"
|
||||||
" [-O keyoffset] [-S keysize] ] ] [-H file]"
|
" [-O keyoffset] [-S keysize] ] ] [-H file]"
|
||||||
|
" [-P protector [-P protector ...]]"
|
||||||
" <SOURCE|-u UUID|-a|-b>"),
|
" <SOURCE|-u UUID|-a|-b>"),
|
||||||
N_("Mount a crypto device."), options);
|
N_("Mount a crypto device."), options);
|
||||||
grub_procfs_register ("luks_script", &luks_script);
|
grub_procfs_register ("luks_script", &luks_script);
|
||||||
|
@ -1597,6 +1906,9 @@ GRUB_MOD_INIT (cryptodisk)
|
||||||
|
|
||||||
GRUB_MOD_FINI (cryptodisk)
|
GRUB_MOD_FINI (cryptodisk)
|
||||||
{
|
{
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
grub_cryptodisk_erasesecrets ();
|
||||||
|
#endif
|
||||||
grub_disk_dev_unregister (&grub_cryptodisk_dev);
|
grub_disk_dev_unregister (&grub_cryptodisk_dev);
|
||||||
cryptodisk_cleanup ();
|
cryptodisk_cleanup ();
|
||||||
grub_unregister_extcmd (cmd);
|
grub_unregister_extcmd (cmd);
|
||||||
|
|
|
@ -20,10 +20,12 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
|
#include <grub/command.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/diskfilter.h>
|
#include <grub/diskfilter.h>
|
||||||
#include <grub/partition.h>
|
#include <grub/partition.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/util/misc.h>
|
#include <grub/util/misc.h>
|
||||||
|
@ -226,14 +228,27 @@ scan_devices (const char *arname)
|
||||||
int need_rescan;
|
int need_rescan;
|
||||||
|
|
||||||
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
||||||
|
{
|
||||||
|
/* look up the crytodisk devices first */
|
||||||
for (p = grub_disk_dev_list; p; p = p->next)
|
for (p = grub_disk_dev_list; p; p = p->next)
|
||||||
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
|
if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID && p->disk_iterate)
|
||||||
&& p->disk_iterate)
|
|
||||||
{
|
{
|
||||||
if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
|
if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
|
||||||
return;
|
return;
|
||||||
if (arname && is_lv_readable (find_lv (arname), 1))
|
if (arname && is_lv_readable (find_lv (arname), 1))
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the devices other than crytodisk */
|
||||||
|
for (p = grub_disk_dev_list; p; p = p->next)
|
||||||
|
if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID && p->disk_iterate)
|
||||||
|
{
|
||||||
|
if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
|
||||||
|
return;
|
||||||
|
if (arname && is_lv_readable (find_lv (arname), 1))
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_depth = 0;
|
scan_depth = 0;
|
||||||
|
@ -966,8 +981,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
|
||||||
|
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
|
||||||
|
|
||||||
/* RAID 1 and single-disk RAID 0 don't use a chunksize but code
|
/* RAID 1 and single-disk RAID 0 don't use a chunksize but code
|
||||||
assumes one so set one. */
|
assumes one so set one. */
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
@ -979,6 +992,10 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
|
||||||
&& lv->segments[i].stripe_size == 0)
|
&& lv->segments[i].stripe_size == 0)
|
||||||
lv->segments[i].stripe_size = 64;
|
lv->segments[i].stripe_size = 64;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
err = validate_lv(lv);
|
err = validate_lv(lv);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1039,7 +1056,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||||
{
|
{
|
||||||
struct grub_diskfilter_vg *array;
|
struct grub_diskfilter_vg *array;
|
||||||
int i;
|
int i;
|
||||||
grub_size_t j;
|
grub_size_t j, sz;
|
||||||
grub_uint64_t totsize;
|
grub_uint64_t totsize;
|
||||||
struct grub_diskfilter_pv *pv;
|
struct grub_diskfilter_pv *pv;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
@ -1140,7 +1157,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||||
}
|
}
|
||||||
array->lvs->vg = array;
|
array->lvs->vg = array;
|
||||||
|
|
||||||
array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
|
if (grub_mul (uuidlen, 2, &sz) ||
|
||||||
|
grub_add (sz, sizeof ("mduuid/"), &sz))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
array->lvs->idname = grub_malloc (sz);
|
||||||
if (!array->lvs->idname)
|
if (!array->lvs->idname)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -1357,6 +1378,86 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_diskfilter_check_pvs_encrypted (grub_disk_t disk, int *pvs_cnt)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *lv = disk->data;
|
||||||
|
struct grub_diskfilter_pv *pv;
|
||||||
|
|
||||||
|
*pvs_cnt = 0;
|
||||||
|
|
||||||
|
if (lv->vg->pvs)
|
||||||
|
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
||||||
|
{
|
||||||
|
(*pvs_cnt)++;
|
||||||
|
|
||||||
|
if (pv->disk == NULL)
|
||||||
|
{
|
||||||
|
/* Can be a partially activated VG, bail out. */
|
||||||
|
return GRUB_ERR_TEST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pv->disk->dev->id != GRUB_DISK_DEVICE_CRYPTODISK_ID)
|
||||||
|
{
|
||||||
|
/* All backing devices must be cryptodisks, stop. */
|
||||||
|
return GRUB_ERR_TEST_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_cmd_cryptocheck (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
int argc, char **args)
|
||||||
|
{
|
||||||
|
grub_disk_t disk;
|
||||||
|
int check_pvs_res;
|
||||||
|
int namelen;
|
||||||
|
int pvs_cnt;
|
||||||
|
int opt_quiet = 0;
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
{
|
||||||
|
if (grub_strcmp (args[0], "--quiet") == 0)
|
||||||
|
{
|
||||||
|
opt_quiet = 1;
|
||||||
|
argc--;
|
||||||
|
args++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized option: %s"), args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != 1)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("disk name expected"));
|
||||||
|
|
||||||
|
namelen = grub_strlen (args[0]);
|
||||||
|
if (namelen > 2 && (args[0][0] == '(') && (args[0][namelen - 1] == ')'))
|
||||||
|
args[0][namelen - 1] = 0;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("invalid disk: %s"),
|
||||||
|
args[0]);
|
||||||
|
|
||||||
|
if (!is_valid_diskfilter_name (&args[0][1]))
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unrecognized disk: %s"),
|
||||||
|
&args[0][1]);
|
||||||
|
|
||||||
|
disk = grub_disk_open (&args[0][1]);
|
||||||
|
if (disk == NULL)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("no such disk: %s"),
|
||||||
|
&args[0][1]);
|
||||||
|
|
||||||
|
check_pvs_res = grub_diskfilter_check_pvs_encrypted (disk, &pvs_cnt);
|
||||||
|
grub_disk_close (disk);
|
||||||
|
if (!opt_quiet)
|
||||||
|
grub_printf ("%s is %sencrypted (%d pv%s examined)\n", &args[0][1],
|
||||||
|
(check_pvs_res == GRUB_ERR_NONE) ? "" : "un",
|
||||||
|
pvs_cnt,
|
||||||
|
(pvs_cnt > 1) ? "s" : "");
|
||||||
|
|
||||||
|
return check_pvs_res;
|
||||||
|
}
|
||||||
|
|
||||||
static struct grub_disk_dev grub_diskfilter_dev =
|
static struct grub_disk_dev grub_diskfilter_dev =
|
||||||
{
|
{
|
||||||
.name = "diskfilter",
|
.name = "diskfilter",
|
||||||
|
@ -1373,14 +1474,21 @@ static struct grub_disk_dev grub_diskfilter_dev =
|
||||||
.next = 0
|
.next = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static grub_command_t cmd;
|
||||||
|
|
||||||
|
|
||||||
GRUB_MOD_INIT(diskfilter)
|
GRUB_MOD_INIT(diskfilter)
|
||||||
{
|
{
|
||||||
grub_disk_dev_register (&grub_diskfilter_dev);
|
grub_disk_dev_register (&grub_diskfilter_dev);
|
||||||
|
cmd = grub_register_command ("cryptocheck", grub_cmd_cryptocheck,
|
||||||
|
N_("[--quiet] DEVICE"),
|
||||||
|
N_("Check if a logical volume resides on encrypted disks."));
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(diskfilter)
|
GRUB_MOD_FINI(diskfilter)
|
||||||
{
|
{
|
||||||
grub_disk_dev_unregister (&grub_diskfilter_dev);
|
grub_disk_dev_unregister (&grub_diskfilter_dev);
|
||||||
|
if (cmd != NULL)
|
||||||
|
grub_unregister_command (cmd);
|
||||||
free_array ();
|
free_array ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/scsicmd.h>
|
#include <grub/scsicmd.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
#include <grub/ieee1275/obdisk.h>
|
#include <grub/ieee1275/obdisk.h>
|
||||||
|
|
||||||
|
@ -128,9 +129,17 @@ count_commas (const char *src)
|
||||||
static char *
|
static char *
|
||||||
decode_grub_devname (const char *name)
|
decode_grub_devname (const char *name)
|
||||||
{
|
{
|
||||||
char *devpath = grub_malloc (grub_strlen (name) + 1);
|
char *devpath;
|
||||||
char *p, c;
|
char *p, c;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
|
if (grub_add (grub_strlen (name), 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device name"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
devpath = grub_malloc (sz);
|
||||||
if (devpath == NULL)
|
if (devpath == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -156,12 +165,20 @@ static char *
|
||||||
encode_grub_devname (const char *path)
|
encode_grub_devname (const char *path)
|
||||||
{
|
{
|
||||||
char *encoding, *optr;
|
char *encoding, *optr;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
encoding = grub_malloc (sizeof (IEEE1275_DEV) + count_commas (path) +
|
if (grub_add (sizeof (IEEE1275_DEV) + 1, count_commas (path), &sz) ||
|
||||||
grub_strlen (path) + 1);
|
grub_add (sz, grub_strlen (path), &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining encoding size"));
|
||||||
|
grub_print_error ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoding = grub_malloc (sz);
|
||||||
|
|
||||||
if (encoding == NULL)
|
if (encoding == NULL)
|
||||||
{
|
{
|
||||||
|
@ -396,8 +413,22 @@ canonicalise_disk (const char *devname)
|
||||||
|
|
||||||
real_unit_str_len = grub_strlen (op->name) + sizeof (IEEE1275_DISK_ALIAS)
|
real_unit_str_len = grub_strlen (op->name) + sizeof (IEEE1275_DISK_ALIAS)
|
||||||
+ grub_strlen (real_unit_address);
|
+ grub_strlen (real_unit_address);
|
||||||
|
if (grub_add (grub_strlen (op->name), sizeof (IEEE1275_DISK_ALIAS), &real_unit_str_len) ||
|
||||||
|
grub_add (real_unit_str_len, grub_strlen (real_unit_address), &real_unit_str_len))
|
||||||
|
{
|
||||||
|
grub_free (parent);
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of canonical name"));
|
||||||
|
grub_print_error ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
real_canon = grub_malloc (real_unit_str_len);
|
real_canon = grub_malloc (real_unit_str_len);
|
||||||
|
if (real_canon == NULL)
|
||||||
|
{
|
||||||
|
grub_free (parent);
|
||||||
|
grub_print_error ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
grub_snprintf (real_canon, real_unit_str_len, "%s/disk@%s",
|
grub_snprintf (real_canon, real_unit_str_len, "%s/disk@%s",
|
||||||
op->name, real_unit_address);
|
op->name, real_unit_address);
|
||||||
|
@ -413,6 +444,7 @@ canonicalise_disk (const char *devname)
|
||||||
static struct disk_dev *
|
static struct disk_dev *
|
||||||
add_canon_disk (const char *cname)
|
add_canon_disk (const char *cname)
|
||||||
{
|
{
|
||||||
|
grub_size_t sz;
|
||||||
struct disk_dev *dev;
|
struct disk_dev *dev;
|
||||||
|
|
||||||
dev = grub_zalloc (sizeof (struct disk_dev));
|
dev = grub_zalloc (sizeof (struct disk_dev));
|
||||||
|
@ -428,13 +460,18 @@ add_canon_disk (const char *cname)
|
||||||
* arguments and allows a client program to open
|
* arguments and allows a client program to open
|
||||||
* the entire (raw) disk. Any disk label is ignored.
|
* the entire (raw) disk. Any disk label is ignored.
|
||||||
*/
|
*/
|
||||||
dev->raw_name = grub_malloc (grub_strlen (cname) + sizeof (":nolabel"));
|
if (grub_add (grub_strlen (cname), sizeof (":nolabel"), &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while appending :nolabel to end of canonical name");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->raw_name = grub_malloc (sz);
|
||||||
|
|
||||||
if (dev->raw_name == NULL)
|
if (dev->raw_name == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
grub_snprintf (dev->raw_name, grub_strlen (cname) + sizeof (":nolabel"),
|
grub_snprintf (dev->raw_name, sz, "%s:nolabel", cname);
|
||||||
"%s:nolabel", cname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <grub/ieee1275/ofdisk.h>
|
#include <grub/ieee1275/ofdisk.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
static char *last_devpath;
|
static char *last_devpath;
|
||||||
static grub_ieee1275_ihandle_t last_ihandle;
|
static grub_ieee1275_ihandle_t last_ihandle;
|
||||||
|
@ -80,6 +81,7 @@ ofdisk_hash_add_real (char *devpath)
|
||||||
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
|
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
|
||||||
const char *iptr;
|
const char *iptr;
|
||||||
char *optr;
|
char *optr;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
p = grub_zalloc (sizeof (*p));
|
p = grub_zalloc (sizeof (*p));
|
||||||
if (!p)
|
if (!p)
|
||||||
|
@ -87,8 +89,14 @@ ofdisk_hash_add_real (char *devpath)
|
||||||
|
|
||||||
p->devpath = devpath;
|
p->devpath = devpath;
|
||||||
|
|
||||||
p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
|
if (grub_mul (grub_strlen (p->devpath), 2, &sz) ||
|
||||||
+ 2 * grub_strlen (p->devpath));
|
grub_add (sz, sizeof ("ieee1275/"), &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->grub_devpath = grub_malloc (sz);
|
||||||
|
|
||||||
if (!p->grub_devpath)
|
if (!p->grub_devpath)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +106,13 @@ ofdisk_hash_add_real (char *devpath)
|
||||||
|
|
||||||
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
|
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
|
||||||
{
|
{
|
||||||
p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
|
if (grub_add (grub_strlen (p->devpath), 3, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of an open path"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->open_path = grub_malloc (sz);
|
||||||
if (!p->open_path)
|
if (!p->open_path)
|
||||||
{
|
{
|
||||||
grub_free (p->grub_devpath);
|
grub_free (p->grub_devpath);
|
||||||
|
@ -224,6 +238,7 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||||
args;
|
args;
|
||||||
char *buf, *bufptr;
|
char *buf, *bufptr;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (grub_ieee1275_open (alias->path, &ihandle))
|
if (grub_ieee1275_open (alias->path, &ihandle))
|
||||||
return;
|
return;
|
||||||
|
@ -243,9 +258,19 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = grub_malloc (grub_strlen (alias->path) + 32);
|
if (grub_add (grub_strlen (alias->path), 32, &sz))
|
||||||
if (!buf)
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for vscsi");
|
||||||
|
grub_ieee1275_close (ihandle);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = grub_malloc (sz);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
grub_ieee1275_close (ihandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
bufptr = grub_stpcpy (buf, alias->path);
|
bufptr = grub_stpcpy (buf, alias->path);
|
||||||
|
|
||||||
for (i = 0; i < args.nentries; i++)
|
for (i = 0; i < args.nentries; i++)
|
||||||
|
@ -287,9 +312,15 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||||
grub_uint64_t *table;
|
grub_uint64_t *table;
|
||||||
grub_uint16_t table_size;
|
grub_uint16_t table_size;
|
||||||
grub_ieee1275_ihandle_t ihandle;
|
grub_ieee1275_ihandle_t ihandle;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
buf = grub_malloc (grub_strlen (alias->path) +
|
if (grub_add (grub_strlen (alias->path), sizeof ("/disk@7766554433221100"), &sz))
|
||||||
sizeof ("/disk@7766554433221100"));
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for sas_ioa");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = grub_malloc (sz);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return;
|
return;
|
||||||
bufptr = grub_stpcpy (buf, alias->path);
|
bufptr = grub_stpcpy (buf, alias->path);
|
||||||
|
@ -427,9 +458,17 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||||
static char *
|
static char *
|
||||||
compute_dev_path (const char *name)
|
compute_dev_path (const char *name)
|
||||||
{
|
{
|
||||||
char *devpath = grub_malloc (grub_strlen (name) + 3);
|
char *devpath;
|
||||||
char *p, c;
|
char *p, c;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
|
if (grub_add (grub_strlen (name), 3, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
devpath = grub_malloc (sz);
|
||||||
if (!devpath)
|
if (!devpath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -625,6 +664,7 @@ insert_bootpath (void)
|
||||||
char *bootpath;
|
char *bootpath;
|
||||||
grub_ssize_t bootpath_size;
|
grub_ssize_t bootpath_size;
|
||||||
char *type;
|
char *type;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
|
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
|
||||||
&bootpath_size)
|
&bootpath_size)
|
||||||
|
@ -635,7 +675,13 @@ insert_bootpath (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
|
if (grub_add (bootpath_size, 64, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining bootpath size"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bootpath = (char *) grub_malloc (sz);
|
||||||
if (! bootpath)
|
if (! bootpath)
|
||||||
{
|
{
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
|
|
73
grub-core/disk/key_protector.c
Normal file
73
grub-core/disk/key_protector.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2022 Microsoft Corporation
|
||||||
|
* Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/list.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/key_protector.h>
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
struct grub_key_protector *grub_key_protectors = NULL;
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_key_protector_register (struct grub_key_protector *protector)
|
||||||
|
{
|
||||||
|
if (protector == NULL || protector->name == NULL || protector->name[0] == '\0')
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for registration");
|
||||||
|
|
||||||
|
if (grub_key_protectors != NULL &&
|
||||||
|
grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector->name) != NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Key protector '%s' already registered", protector->name);
|
||||||
|
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors), GRUB_AS_LIST (protector));
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_key_protector_unregister (struct grub_key_protector *protector)
|
||||||
|
{
|
||||||
|
if (protector == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for unregistration");
|
||||||
|
|
||||||
|
grub_list_remove (GRUB_AS_LIST (protector));
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_key_protector_recover_key (const char *protector, grub_uint8_t **key,
|
||||||
|
grub_size_t *key_size)
|
||||||
|
{
|
||||||
|
struct grub_key_protector *kp = NULL;
|
||||||
|
|
||||||
|
if (grub_key_protectors == NULL)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "No key protector registered");
|
||||||
|
|
||||||
|
if (protector == NULL || protector[0] == '\0')
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector");
|
||||||
|
|
||||||
|
kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector);
|
||||||
|
if (kp == NULL)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Key protector '%s' not found", protector);
|
||||||
|
|
||||||
|
return kp->recover_key (key, key_size);
|
||||||
|
}
|
|
@ -179,6 +179,36 @@ gpt_ldm_sector (grub_disk_t dsk)
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_pv (struct grub_diskfilter_pv *pv)
|
||||||
|
{
|
||||||
|
if (pv == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
grub_free (pv->internal_id);
|
||||||
|
grub_free (pv->id.uuid);
|
||||||
|
grub_free (pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_lv (struct grub_diskfilter_lv *lv)
|
||||||
|
{
|
||||||
|
if (lv == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv->fullname);
|
||||||
|
if (lv->segments)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
grub_free (lv->segments[i].nodes);
|
||||||
|
grub_free (lv->segments);
|
||||||
|
}
|
||||||
|
grub_free (lv);
|
||||||
|
}
|
||||||
|
|
||||||
static struct grub_diskfilter_vg *
|
static struct grub_diskfilter_vg *
|
||||||
make_vg (grub_disk_t disk,
|
make_vg (grub_disk_t disk,
|
||||||
const struct grub_ldm_label *label)
|
const struct grub_ldm_label *label)
|
||||||
|
@ -196,12 +226,8 @@ make_vg (grub_disk_t disk,
|
||||||
vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
|
vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
|
||||||
vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
|
vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
|
||||||
if (! vg->uuid || !vg->name)
|
if (! vg->uuid || !vg->name)
|
||||||
{
|
goto fail1;
|
||||||
grub_free (vg->uuid);
|
|
||||||
grub_free (vg->name);
|
|
||||||
grub_free (vg);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
|
grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
|
||||||
grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
|
grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
|
||||||
vg->name[LDM_NAME_STRLEN] = 0;
|
vg->name[LDM_NAME_STRLEN] = 0;
|
||||||
|
@ -220,6 +246,7 @@ make_vg (grub_disk_t disk,
|
||||||
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
/ sizeof (struct grub_ldm_vblk)];
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
grub_size_t sz;
|
||||||
err = grub_disk_read (disk, cursec, 0,
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
sizeof(vblk), &vblk);
|
sizeof(vblk), &vblk);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -251,12 +278,18 @@ make_vg (grub_disk_t disk,
|
||||||
grub_free (pv);
|
grub_free (pv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
pv->internal_id = grub_malloc (ptr[0] + 2);
|
if (grub_add (ptr[0], 2, &sz))
|
||||||
if (!pv->internal_id)
|
|
||||||
{
|
{
|
||||||
grub_free (pv);
|
grub_free (pv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pv->internal_id = grub_malloc (sz);
|
||||||
|
if (!pv->internal_id)
|
||||||
|
{
|
||||||
|
free_pv (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
|
grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
|
||||||
pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
|
pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
|
||||||
|
|
||||||
|
@ -264,7 +297,7 @@ make_vg (grub_disk_t disk,
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (pv);
|
free_pv (pv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
/* ptr = name. */
|
/* ptr = name. */
|
||||||
|
@ -272,11 +305,23 @@ make_vg (grub_disk_t disk,
|
||||||
if (ptr + *ptr + 1
|
if (ptr + *ptr + 1
|
||||||
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (pv);
|
free_pv (pv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
pv->id.uuidlen = *ptr;
|
pv->id.uuidlen = *ptr;
|
||||||
pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
|
|
||||||
|
if (grub_add (pv->id.uuidlen, 1, &sz))
|
||||||
|
{
|
||||||
|
free_pv (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pv->id.uuid = grub_malloc (sz);
|
||||||
|
if (pv->id.uuid == NULL)
|
||||||
|
{
|
||||||
|
free_pv (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
||||||
pv->id.uuid[pv->id.uuidlen] = 0;
|
pv->id.uuid[pv->id.uuidlen] = 0;
|
||||||
|
|
||||||
|
@ -322,7 +367,7 @@ make_vg (grub_disk_t disk,
|
||||||
lv->segments = grub_zalloc (sizeof (*lv->segments));
|
lv->segments = grub_zalloc (sizeof (*lv->segments));
|
||||||
if (!lv->segments)
|
if (!lv->segments)
|
||||||
{
|
{
|
||||||
grub_free (lv);
|
free_lv (lv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
lv->segments->start_extent = 0;
|
lv->segments->start_extent = 0;
|
||||||
|
@ -333,20 +378,25 @@ make_vg (grub_disk_t disk,
|
||||||
sizeof (*lv->segments->nodes));
|
sizeof (*lv->segments->nodes));
|
||||||
if (!lv->segments->nodes)
|
if (!lv->segments->nodes)
|
||||||
{
|
{
|
||||||
grub_free (lv);
|
free_lv (lv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
ptr = vblk[i].dynamic;
|
ptr = vblk[i].dynamic;
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv);
|
free_lv (lv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
if (grub_add (ptr[0], 2, &sz))
|
||||||
|
{
|
||||||
|
free_lv (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
lv->internal_id = grub_malloc (sz);
|
||||||
if (!lv->internal_id)
|
if (!lv->internal_id)
|
||||||
{
|
{
|
||||||
grub_free (lv);
|
free_lv (lv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
|
grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
|
||||||
|
@ -356,20 +406,18 @@ make_vg (grub_disk_t disk,
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv);
|
free_lv (lv);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
if (grub_add (*ptr, 1, &sz))
|
if (grub_add (*ptr, 1, &sz))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
lv->name = grub_malloc (sz);
|
lv->name = grub_malloc (sz);
|
||||||
if (!lv->name)
|
if (!lv->name)
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
grub_memcpy (lv->name, ptr + 1, *ptr);
|
grub_memcpy (lv->name, ptr + 1, *ptr);
|
||||||
|
@ -378,36 +426,28 @@ make_vg (grub_disk_t disk,
|
||||||
vg->uuid, lv->name);
|
vg->uuid, lv->name);
|
||||||
if (!lv->fullname)
|
if (!lv->fullname)
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr + *ptr + 1
|
if (ptr + *ptr + 1
|
||||||
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
/* ptr = volume type. */
|
/* ptr = volume type. */
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
/* ptr = flags. */
|
/* ptr = flags. */
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,17 +456,13 @@ make_vg (grub_disk_t disk,
|
||||||
/* ptr = number of children. */
|
/* ptr = number of children. */
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +472,7 @@ make_vg (grub_disk_t disk,
|
||||||
|| ptr + *ptr + 1>= vblk[i].dynamic
|
|| ptr + *ptr + 1>= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (lv->internal_id);
|
free_lv (lv);
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
lv->size = read_int (ptr + 1, *ptr);
|
lv->size = read_int (ptr + 1, *ptr);
|
||||||
|
@ -455,6 +489,7 @@ make_vg (grub_disk_t disk,
|
||||||
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
/ sizeof (struct grub_ldm_vblk)];
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
grub_size_t sz;
|
||||||
err = grub_disk_read (disk, cursec, 0,
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
sizeof(vblk), &vblk);
|
sizeof(vblk), &vblk);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -487,13 +522,18 @@ make_vg (grub_disk_t disk,
|
||||||
ptr = vblk[i].dynamic;
|
ptr = vblk[i].dynamic;
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp);
|
free_lv (comp);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
if (grub_add (ptr[0], 2, &sz))
|
||||||
|
{
|
||||||
|
free_lv (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
comp->internal_id = grub_malloc (sz);
|
||||||
if (!comp->internal_id)
|
if (!comp->internal_id)
|
||||||
{
|
{
|
||||||
grub_free (comp);
|
free_lv (comp);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
|
grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
|
||||||
|
@ -502,16 +542,14 @@ make_vg (grub_disk_t disk,
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
/* ptr = name. */
|
/* ptr = name. */
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
/* ptr = state. */
|
/* ptr = state. */
|
||||||
|
@ -521,8 +559,7 @@ make_vg (grub_disk_t disk,
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,16 +567,14 @@ make_vg (grub_disk_t disk,
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
ptr += 8 + 8;
|
ptr += 8 + 8;
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
@ -550,8 +585,7 @@ make_vg (grub_disk_t disk,
|
||||||
}
|
}
|
||||||
if (!lv)
|
if (!lv)
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
comp->size = lv->size;
|
comp->size = lv->size;
|
||||||
|
@ -563,8 +597,7 @@ make_vg (grub_disk_t disk,
|
||||||
sizeof (*comp->segments));
|
sizeof (*comp->segments));
|
||||||
if (!comp->segments)
|
if (!comp->segments)
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,8 +608,7 @@ make_vg (grub_disk_t disk,
|
||||||
comp->segments = grub_malloc (sizeof (*comp->segments));
|
comp->segments = grub_malloc (sizeof (*comp->segments));
|
||||||
if (!comp->segments)
|
if (!comp->segments)
|
||||||
{
|
{
|
||||||
grub_free (comp->internal_id);
|
free_lv (comp);
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
comp->segments->start_extent = 0;
|
comp->segments->start_extent = 0;
|
||||||
|
@ -591,27 +623,21 @@ make_vg (grub_disk_t disk,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
grub_free (comp->segments);
|
free_lv (comp);
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
ptr += *ptr + 1;
|
ptr += *ptr + 1;
|
||||||
ptr++;
|
ptr++;
|
||||||
if (!(vblk[i].flags & 0x10))
|
if (!(vblk[i].flags & 0x10))
|
||||||
{
|
{
|
||||||
grub_free (comp->segments);
|
free_lv (comp);
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|| ptr + *ptr + 1 >= vblk[i].dynamic
|
|| ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->segments);
|
free_lv (comp);
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
comp->segments->stripe_size = read_int (ptr + 1, *ptr);
|
comp->segments->stripe_size = read_int (ptr + 1, *ptr);
|
||||||
|
@ -619,20 +645,16 @@ make_vg (grub_disk_t disk,
|
||||||
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
+ sizeof (vblk[i].dynamic))
|
+ sizeof (vblk[i].dynamic))
|
||||||
{
|
{
|
||||||
grub_free (comp->segments);
|
free_lv (comp);
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
comp->segments->node_count = read_int (ptr + 1, *ptr);
|
comp->segments->node_count = read_int (ptr + 1, *ptr);
|
||||||
comp->segments->node_alloc = comp->segments->node_count;
|
comp->segments->node_alloc = comp->segments->node_count;
|
||||||
comp->segments->nodes = grub_calloc (comp->segments->node_alloc,
|
comp->segments->nodes = grub_calloc (comp->segments->node_alloc,
|
||||||
sizeof (*comp->segments->nodes));
|
sizeof (*comp->segments->nodes));
|
||||||
if (!lv->segments->nodes)
|
if (comp->segments->nodes == NULL)
|
||||||
{
|
{
|
||||||
grub_free (comp->segments);
|
free_lv (comp);
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,25 +662,18 @@ make_vg (grub_disk_t disk,
|
||||||
if (lv->segments->node_alloc == lv->segments->node_count)
|
if (lv->segments->node_alloc == lv->segments->node_count)
|
||||||
{
|
{
|
||||||
void *t;
|
void *t;
|
||||||
grub_size_t sz;
|
|
||||||
|
|
||||||
if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
|
if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
|
||||||
grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
|
grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
|
||||||
{
|
{
|
||||||
grub_free (comp->segments->nodes);
|
free_lv (comp);
|
||||||
grub_free (comp->segments);
|
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = grub_realloc (lv->segments->nodes, sz);
|
t = grub_realloc (lv->segments->nodes, sz);
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
grub_free (comp->segments->nodes);
|
free_lv (comp);
|
||||||
grub_free (comp->segments);
|
|
||||||
grub_free (comp->internal_id);
|
|
||||||
grub_free (comp);
|
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
lv->segments->nodes = t;
|
lv->segments->nodes = t;
|
||||||
|
@ -798,7 +813,10 @@ make_vg (grub_disk_t disk,
|
||||||
comp->segments[comp->segment_count].nodes
|
comp->segments[comp->segment_count].nodes
|
||||||
= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
|
= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
|
||||||
if (!comp->segments[comp->segment_count].nodes)
|
if (!comp->segments[comp->segment_count].nodes)
|
||||||
|
{
|
||||||
|
grub_free (comp->segments);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
}
|
||||||
comp->segments[comp->segment_count].nodes[0] = part;
|
comp->segments[comp->segment_count].nodes[0] = part;
|
||||||
comp->segment_count++;
|
comp->segment_count++;
|
||||||
}
|
}
|
||||||
|
@ -813,25 +831,19 @@ make_vg (grub_disk_t disk,
|
||||||
struct grub_diskfilter_pv *pv, *next_pv;
|
struct grub_diskfilter_pv *pv, *next_pv;
|
||||||
for (lv = vg->lvs; lv; lv = next_lv)
|
for (lv = vg->lvs; lv; lv = next_lv)
|
||||||
{
|
{
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
|
||||||
grub_free (lv->segments[i].nodes);
|
|
||||||
|
|
||||||
next_lv = lv->next;
|
next_lv = lv->next;
|
||||||
grub_free (lv->segments);
|
free_lv (lv);
|
||||||
grub_free (lv->internal_id);
|
|
||||||
grub_free (lv->name);
|
|
||||||
grub_free (lv->fullname);
|
|
||||||
grub_free (lv);
|
|
||||||
}
|
}
|
||||||
for (pv = vg->pvs; pv; pv = next_pv)
|
for (pv = vg->pvs; pv; pv = next_pv)
|
||||||
{
|
{
|
||||||
next_pv = pv->next;
|
next_pv = pv->next;
|
||||||
grub_free (pv->id.uuid);
|
free_pv (pv);
|
||||||
grub_free (pv);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fail1:
|
||||||
grub_free (vg->uuid);
|
grub_free (vg->uuid);
|
||||||
|
grub_free (vg->name);
|
||||||
grub_free (vg);
|
grub_free (vg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ struct grub_loopback
|
||||||
grub_file_t file;
|
grub_file_t file;
|
||||||
struct grub_loopback *next;
|
struct grub_loopback *next;
|
||||||
unsigned long id;
|
unsigned long id;
|
||||||
|
grub_uint64_t refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct grub_loopback *loopback_list;
|
static struct grub_loopback *loopback_list;
|
||||||
|
@ -64,6 +66,8 @@ delete_loopback (const char *name)
|
||||||
if (! dev)
|
if (! dev)
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE, "device not found");
|
return grub_error (GRUB_ERR_BAD_DEVICE, "device not found");
|
||||||
|
|
||||||
|
if (dev->refcnt > 0)
|
||||||
|
return grub_error (GRUB_ERR_STILL_REFERENCED, "device still referenced");
|
||||||
/* Remove the device from the list. */
|
/* Remove the device from the list. */
|
||||||
*prev = dev->next;
|
*prev = dev->next;
|
||||||
|
|
||||||
|
@ -120,6 +124,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
|
|
||||||
newdev->file = file;
|
newdev->file = file;
|
||||||
newdev->id = last_id++;
|
newdev->id = last_id++;
|
||||||
|
newdev->refcnt = 0;
|
||||||
|
|
||||||
/* Add the new entry to the list. */
|
/* Add the new entry to the list. */
|
||||||
newdev->next = loopback_list;
|
newdev->next = loopback_list;
|
||||||
|
@ -161,6 +166,9 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
||||||
if (! dev)
|
if (! dev)
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
||||||
|
|
||||||
|
if (grub_add (dev->refcnt, 1, &dev->refcnt))
|
||||||
|
grub_fatal ("Reference count overflow");
|
||||||
|
|
||||||
/* Use the filesize for the disk size, round up to a complete sector. */
|
/* Use the filesize for the disk size, round up to a complete sector. */
|
||||||
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
|
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
|
||||||
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||||
|
@ -178,6 +186,15 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_loopback_close (grub_disk_t disk)
|
||||||
|
{
|
||||||
|
struct grub_loopback *dev = disk->data;
|
||||||
|
|
||||||
|
if (grub_sub (dev->refcnt, 1, &dev->refcnt))
|
||||||
|
grub_fatal ("Reference count underflow");
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
|
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_size_t size, char *buf)
|
grub_size_t size, char *buf)
|
||||||
|
@ -220,6 +237,7 @@ static struct grub_disk_dev grub_loopback_dev =
|
||||||
.id = GRUB_DISK_DEVICE_LOOPBACK_ID,
|
.id = GRUB_DISK_DEVICE_LOOPBACK_ID,
|
||||||
.disk_iterate = grub_loopback_iterate,
|
.disk_iterate = grub_loopback_iterate,
|
||||||
.disk_open = grub_loopback_open,
|
.disk_open = grub_loopback_open,
|
||||||
|
.disk_close = grub_loopback_close,
|
||||||
.disk_read = grub_loopback_read,
|
.disk_read = grub_loopback_read,
|
||||||
.disk_write = grub_loopback_write,
|
.disk_write = grub_loopback_write,
|
||||||
.next = 0
|
.next = 0
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/crypto.h>
|
#include <grub/crypto.h>
|
||||||
#include <grub/partition.h>
|
#include <grub/partition.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
#include <base64.h>
|
#include <base64.h>
|
||||||
#include <json.h>
|
#include <json.h>
|
||||||
|
@ -569,6 +570,7 @@ luks2_recover_key (grub_disk_t source,
|
||||||
gcry_err_code_t gcry_ret;
|
gcry_err_code_t gcry_ret;
|
||||||
grub_json_t *json = NULL, keyslots;
|
grub_json_t *json = NULL, keyslots;
|
||||||
grub_err_t ret;
|
grub_err_t ret;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (cargs->key_data == NULL || cargs->key_len == 0)
|
if (cargs->key_data == NULL || cargs->key_len == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
|
||||||
|
@ -577,7 +579,12 @@ luks2_recover_key (grub_disk_t source,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
json_header = grub_zalloc (grub_be_to_cpu64 (header.hdr_size) - sizeof (header));
|
grub_puts_ (N_("Attempting to decrypt master key..."));
|
||||||
|
|
||||||
|
if (grub_sub (grub_be_to_cpu64 (header.hdr_size), sizeof (header), &sz))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while calculating json header size");
|
||||||
|
|
||||||
|
json_header = grub_zalloc (sz);
|
||||||
if (!json_header)
|
if (!json_header)
|
||||||
return GRUB_ERR_OUT_OF_MEMORY;
|
return GRUB_ERR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,11 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
struct cache_lv
|
struct ignored_feature_lv
|
||||||
{
|
{
|
||||||
struct grub_diskfilter_lv *lv;
|
struct grub_diskfilter_lv *lv;
|
||||||
char *cache_pool;
|
|
||||||
char *origin;
|
char *origin;
|
||||||
struct cache_lv *next;
|
struct ignored_feature_lv *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,30 +104,29 @@ grub_lvm_check_flag (const char *p, const char *str, const char *flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_lvm_free_cache_lvs (struct cache_lv *cache_lvs)
|
grub_lvm_free_ignored_feature_lvs (struct ignored_feature_lv *ignored_feature_lvs)
|
||||||
{
|
{
|
||||||
struct cache_lv *cache;
|
struct ignored_feature_lv *ignored_feature;
|
||||||
|
|
||||||
while ((cache = cache_lvs))
|
while ((ignored_feature = ignored_feature_lvs))
|
||||||
{
|
{
|
||||||
cache_lvs = cache_lvs->next;
|
ignored_feature_lvs = ignored_feature_lvs->next;
|
||||||
|
|
||||||
if (cache->lv)
|
if (ignored_feature->lv)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < cache->lv->segment_count; ++i)
|
for (i = 0; i < ignored_feature->lv->segment_count; ++i)
|
||||||
if (cache->lv->segments)
|
if (ignored_feature->lv->segments)
|
||||||
grub_free (cache->lv->segments[i].nodes);
|
grub_free (ignored_feature->lv->segments[i].nodes);
|
||||||
grub_free (cache->lv->segments);
|
grub_free (ignored_feature->lv->segments);
|
||||||
grub_free (cache->lv->fullname);
|
grub_free (ignored_feature->lv->fullname);
|
||||||
grub_free (cache->lv->idname);
|
grub_free (ignored_feature->lv->idname);
|
||||||
grub_free (cache->lv->name);
|
grub_free (ignored_feature->lv->name);
|
||||||
}
|
}
|
||||||
grub_free (cache->lv);
|
grub_free (ignored_feature->lv);
|
||||||
grub_free (cache->origin);
|
grub_free (ignored_feature->origin);
|
||||||
grub_free (cache->cache_pool);
|
grub_free (ignored_feature);
|
||||||
grub_free (cache);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +288,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
|
|
||||||
p = q = (char *)ptr;
|
p = q = (char *)ptr;
|
||||||
|
|
||||||
if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
|
if (grub_add (ptr, (grub_size_t) grub_le_to_cpu64 (rlocn->size), &ptr))
|
||||||
goto error_parsing_metadata;
|
goto error_parsing_metadata;
|
||||||
|
|
||||||
mda_end = (char *)ptr;
|
mda_end = (char *)ptr;
|
||||||
|
@ -325,7 +323,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
|
|
||||||
if (! vg)
|
if (! vg)
|
||||||
{
|
{
|
||||||
struct cache_lv *cache_lvs = NULL;
|
struct ignored_feature_lv *ignored_feature_lvs = NULL;
|
||||||
|
|
||||||
/* First time we see this volume group. We've to create the
|
/* First time we see this volume group. We've to create the
|
||||||
whole volume group structure. */
|
whole volume group structure. */
|
||||||
|
@ -370,6 +368,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pv = grub_zalloc (sizeof (*pv));
|
pv = grub_zalloc (sizeof (*pv));
|
||||||
|
if (pv == NULL)
|
||||||
|
goto fail4;
|
||||||
q = p;
|
q = p;
|
||||||
while (*q != ' ' && q < mda_end)
|
while (*q != ' ' && q < mda_end)
|
||||||
q++;
|
q++;
|
||||||
|
@ -379,6 +379,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
|
|
||||||
s = q - p;
|
s = q - p;
|
||||||
pv->name = grub_malloc (s + 1);
|
pv->name = grub_malloc (s + 1);
|
||||||
|
if (pv->name == NULL)
|
||||||
|
goto pvs_fail_noname;
|
||||||
grub_memcpy (pv->name, p, s);
|
grub_memcpy (pv->name, p, s);
|
||||||
pv->name[s] = '\0';
|
pv->name[s] = '\0';
|
||||||
|
|
||||||
|
@ -451,6 +453,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
lv = grub_zalloc (sizeof (*lv));
|
lv = grub_zalloc (sizeof (*lv));
|
||||||
|
if (lv == NULL)
|
||||||
|
goto fail4;
|
||||||
|
|
||||||
q = p;
|
q = p;
|
||||||
while (*q != ' ' && q < mda_end)
|
while (*q != ' ' && q < mda_end)
|
||||||
|
@ -545,6 +549,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
goto lvs_fail;
|
goto lvs_fail;
|
||||||
}
|
}
|
||||||
lv->segments = grub_calloc (lv->segment_count, sizeof (*seg));
|
lv->segments = grub_calloc (lv->segment_count, sizeof (*seg));
|
||||||
|
if (lv->segments == NULL)
|
||||||
|
goto lvs_fail;
|
||||||
seg = lv->segments;
|
seg = lv->segments;
|
||||||
|
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
@ -612,6 +618,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
|
|
||||||
seg->nodes = grub_calloc (seg->node_count,
|
seg->nodes = grub_calloc (seg->node_count,
|
||||||
sizeof (*stripe));
|
sizeof (*stripe));
|
||||||
|
if (seg->nodes == NULL)
|
||||||
|
goto lvs_segment_fail;
|
||||||
stripe = seg->nodes;
|
stripe = seg->nodes;
|
||||||
|
|
||||||
p = grub_strstr (p, "stripes = [");
|
p = grub_strstr (p, "stripes = [");
|
||||||
|
@ -671,8 +679,9 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
goto lvs_segment_fail;
|
goto lvs_segment_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||||
* seg->node_count);
|
if (seg->nodes == NULL)
|
||||||
|
goto lvs_segment_fail;
|
||||||
|
|
||||||
p = grub_strstr (p, "mirrors = [");
|
p = grub_strstr (p, "mirrors = [");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
|
@ -760,8 +769,9 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0]));
|
||||||
* seg->node_count);
|
if (seg->nodes == NULL)
|
||||||
|
goto lvs_segment_fail;
|
||||||
|
|
||||||
p = grub_strstr (p, "raids = [");
|
p = grub_strstr (p, "raids = [");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
|
@ -807,108 +817,98 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
seg->nodes[seg->node_count - 1].name = tmp;
|
seg->nodes[seg->node_count - 1].name = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (grub_memcmp (p, "cache\"",
|
/*
|
||||||
sizeof ("cache\"") - 1) == 0)
|
* Cache and integrity LVs have extra parts that
|
||||||
|
* we can ignore for our read-only access.
|
||||||
|
*/
|
||||||
|
else if (grub_strncmp (p, "cache\"", sizeof ("cache\"") - 1) == 0 ||
|
||||||
|
grub_strncmp (p, "cache+CACHE_USES_CACHEVOL\"", sizeof ("cache+CACHE_USES_CACHEVOL\"") - 1) == 0 ||
|
||||||
|
grub_strncmp (p, "integrity\"", sizeof ("integrity\"") - 1) == 0)
|
||||||
{
|
{
|
||||||
struct cache_lv *cache = NULL;
|
struct ignored_feature_lv *ignored_feature = NULL;
|
||||||
|
|
||||||
char *p2, *p3;
|
char *p2, *p3;
|
||||||
grub_size_t sz;
|
grub_size_t sz;
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
p2 = grub_strchr (p, '"');
|
||||||
|
if (p2)
|
||||||
|
*p2 = '\0';
|
||||||
|
grub_util_info ("Ignoring extra metadata type '%s' for %s", p, lv->name);
|
||||||
|
if (p2)
|
||||||
|
*p2 ='"';
|
||||||
|
#endif
|
||||||
|
|
||||||
cache = grub_zalloc (sizeof (*cache));
|
ignored_feature = grub_zalloc (sizeof (*ignored_feature));
|
||||||
if (!cache)
|
if (!ignored_feature)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
cache->lv = grub_zalloc (sizeof (*cache->lv));
|
ignored_feature->lv = grub_zalloc (sizeof (*ignored_feature->lv));
|
||||||
if (!cache->lv)
|
if (!ignored_feature->lv)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
grub_memcpy (cache->lv, lv, sizeof (*cache->lv));
|
grub_memcpy (ignored_feature->lv, lv, sizeof (*ignored_feature->lv));
|
||||||
|
|
||||||
if (lv->fullname)
|
if (lv->fullname)
|
||||||
{
|
{
|
||||||
cache->lv->fullname = grub_strdup (lv->fullname);
|
ignored_feature->lv->fullname = grub_strdup (lv->fullname);
|
||||||
if (!cache->lv->fullname)
|
if (!ignored_feature->lv->fullname)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
}
|
}
|
||||||
if (lv->idname)
|
if (lv->idname)
|
||||||
{
|
{
|
||||||
cache->lv->idname = grub_strdup (lv->idname);
|
ignored_feature->lv->idname = grub_strdup (lv->idname);
|
||||||
if (!cache->lv->idname)
|
if (!ignored_feature->lv->idname)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
}
|
}
|
||||||
if (lv->name)
|
if (lv->name)
|
||||||
{
|
{
|
||||||
cache->lv->name = grub_strdup (lv->name);
|
ignored_feature->lv->name = grub_strdup (lv->name);
|
||||||
if (!cache->lv->name)
|
if (!ignored_feature->lv->name)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_lv = 1;
|
skip_lv = 1;
|
||||||
|
|
||||||
p2 = grub_strstr (p, "cache_pool = \"");
|
|
||||||
if (!p2)
|
|
||||||
goto cache_lv_fail;
|
|
||||||
|
|
||||||
p2 = grub_strchr (p2, '"');
|
|
||||||
if (!p2)
|
|
||||||
goto cache_lv_fail;
|
|
||||||
|
|
||||||
p3 = ++p2;
|
|
||||||
if (p3 == mda_end)
|
|
||||||
goto cache_lv_fail;
|
|
||||||
p3 = grub_strchr (p3, '"');
|
|
||||||
if (!p3)
|
|
||||||
goto cache_lv_fail;
|
|
||||||
|
|
||||||
sz = p3 - p2;
|
|
||||||
|
|
||||||
cache->cache_pool = grub_malloc (sz + 1);
|
|
||||||
if (!cache->cache_pool)
|
|
||||||
goto cache_lv_fail;
|
|
||||||
grub_memcpy (cache->cache_pool, p2, sz);
|
|
||||||
cache->cache_pool[sz] = '\0';
|
|
||||||
|
|
||||||
p2 = grub_strstr (p, "origin = \"");
|
p2 = grub_strstr (p, "origin = \"");
|
||||||
if (!p2)
|
if (!p2)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
|
|
||||||
p2 = grub_strchr (p2, '"');
|
p2 = grub_strchr (p2, '"');
|
||||||
if (!p2)
|
if (!p2)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
|
|
||||||
p3 = ++p2;
|
p3 = ++p2;
|
||||||
if (p3 == mda_end)
|
if (p3 == mda_end)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
p3 = grub_strchr (p3, '"');
|
p3 = grub_strchr (p3, '"');
|
||||||
if (!p3)
|
if (!p3)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
|
|
||||||
sz = p3 - p2;
|
sz = p3 - p2;
|
||||||
|
|
||||||
cache->origin = grub_malloc (sz + 1);
|
ignored_feature->origin = grub_malloc (sz + 1);
|
||||||
if (!cache->origin)
|
if (!ignored_feature->origin)
|
||||||
goto cache_lv_fail;
|
goto ignored_feature_lv_fail;
|
||||||
grub_memcpy (cache->origin, p2, sz);
|
grub_memcpy (ignored_feature->origin, p2, sz);
|
||||||
cache->origin[sz] = '\0';
|
ignored_feature->origin[sz] = '\0';
|
||||||
|
|
||||||
cache->next = cache_lvs;
|
ignored_feature->next = ignored_feature_lvs;
|
||||||
cache_lvs = cache;
|
ignored_feature_lvs = ignored_feature;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cache_lv_fail:
|
ignored_feature_lv_fail:
|
||||||
if (cache)
|
if (ignored_feature)
|
||||||
{
|
{
|
||||||
grub_free (cache->origin);
|
grub_free (ignored_feature->origin);
|
||||||
grub_free (cache->cache_pool);
|
if (ignored_feature->lv)
|
||||||
if (cache->lv)
|
|
||||||
{
|
{
|
||||||
grub_free (cache->lv->fullname);
|
grub_free (ignored_feature->lv->fullname);
|
||||||
grub_free (cache->lv->idname);
|
grub_free (ignored_feature->lv->idname);
|
||||||
grub_free (cache->lv->name);
|
grub_free (ignored_feature->lv->name);
|
||||||
}
|
}
|
||||||
grub_free (cache->lv);
|
grub_free (ignored_feature->lv);
|
||||||
grub_free (cache);
|
grub_free (ignored_feature);
|
||||||
}
|
}
|
||||||
grub_lvm_free_cache_lvs (cache_lvs);
|
grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
|
||||||
goto fail4;
|
goto fail4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -917,7 +917,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
char *p2;
|
char *p2;
|
||||||
p2 = grub_strchr (p, '"');
|
p2 = grub_strchr (p, '"');
|
||||||
if (p2)
|
if (p2)
|
||||||
*p2 = 0;
|
*p2 = '\0';
|
||||||
grub_util_info ("unknown LVM type %s", p);
|
grub_util_info ("unknown LVM type %s", p);
|
||||||
if (p2)
|
if (p2)
|
||||||
*p2 ='"';
|
*p2 ='"';
|
||||||
|
@ -961,10 +961,68 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Match lvs. */
|
|
||||||
|
{
|
||||||
|
struct ignored_feature_lv *ignored_feature;
|
||||||
|
|
||||||
|
for (ignored_feature = ignored_feature_lvs; ignored_feature; ignored_feature = ignored_feature->next)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *lv;
|
||||||
|
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
if (grub_strcmp (lv->name, ignored_feature->origin) == 0)
|
||||||
|
break;
|
||||||
|
if (lv)
|
||||||
|
{
|
||||||
|
ignored_feature->lv->segments = grub_calloc (lv->segment_count, sizeof (*lv->segments));
|
||||||
|
if (!ignored_feature->lv->segments)
|
||||||
|
{
|
||||||
|
grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
|
||||||
|
goto fail4;
|
||||||
|
}
|
||||||
|
grub_memcpy (ignored_feature->lv->segments, lv->segments, lv->segment_count * sizeof (*lv->segments));
|
||||||
|
|
||||||
|
for (i = 0; i < lv->segment_count; ++i)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_node *nodes = lv->segments[i].nodes;
|
||||||
|
grub_size_t node_count = lv->segments[i].node_count;
|
||||||
|
|
||||||
|
ignored_feature->lv->segments[i].nodes = grub_calloc (node_count, sizeof (*nodes));
|
||||||
|
if (!ignored_feature->lv->segments[i].nodes)
|
||||||
|
{
|
||||||
|
for (j = 0; j < i; ++j)
|
||||||
|
grub_free (ignored_feature->lv->segments[j].nodes);
|
||||||
|
grub_free (ignored_feature->lv->segments);
|
||||||
|
ignored_feature->lv->segments = NULL;
|
||||||
|
grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
|
||||||
|
goto fail4;
|
||||||
|
}
|
||||||
|
grub_memcpy (ignored_feature->lv->segments[i].nodes, nodes, node_count * sizeof (*nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignored_feature->lv->segments)
|
||||||
|
{
|
||||||
|
ignored_feature->lv->segment_count = lv->segment_count;
|
||||||
|
ignored_feature->lv->vg = vg;
|
||||||
|
ignored_feature->lv->next = vg->lvs;
|
||||||
|
vg->lvs = ignored_feature->lv;
|
||||||
|
ignored_feature->lv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("Couldn't find LVM part of ignored feature on %s", ignored_feature->origin);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match LVs. Must be done after cache and integrity are found. */
|
||||||
{
|
{
|
||||||
struct grub_diskfilter_lv *lv1;
|
struct grub_diskfilter_lv *lv1;
|
||||||
struct grub_diskfilter_lv *lv2;
|
struct grub_diskfilter_lv *lv2;
|
||||||
|
|
||||||
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
|
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
|
||||||
for (i = 0; i < lv1->segment_count; i++)
|
for (i = 0; i < lv1->segment_count; i++)
|
||||||
for (j = 0; j < lv1->segments[i].node_count; j++)
|
for (j = 0; j < lv1->segments[i].node_count; j++)
|
||||||
|
@ -989,60 +1047,9 @@ grub_lvm_detect (grub_disk_t disk,
|
||||||
lv1->segments[i].nodes[j].lv = lv2;
|
lv1->segments[i].nodes[j].lv = lv2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
|
||||||
struct cache_lv *cache;
|
|
||||||
|
|
||||||
for (cache = cache_lvs; cache; cache = cache->next)
|
|
||||||
{
|
|
||||||
struct grub_diskfilter_lv *lv;
|
|
||||||
|
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
|
||||||
if (grub_strcmp (lv->name, cache->origin) == 0)
|
|
||||||
break;
|
|
||||||
if (lv)
|
|
||||||
{
|
|
||||||
cache->lv->segments = grub_calloc (lv->segment_count, sizeof (*lv->segments));
|
|
||||||
if (!cache->lv->segments)
|
|
||||||
{
|
|
||||||
grub_lvm_free_cache_lvs (cache_lvs);
|
|
||||||
goto fail4;
|
|
||||||
}
|
|
||||||
grub_memcpy (cache->lv->segments, lv->segments, lv->segment_count * sizeof (*lv->segments));
|
|
||||||
|
|
||||||
for (i = 0; i < lv->segment_count; ++i)
|
|
||||||
{
|
|
||||||
struct grub_diskfilter_node *nodes = lv->segments[i].nodes;
|
|
||||||
grub_size_t node_count = lv->segments[i].node_count;
|
|
||||||
|
|
||||||
cache->lv->segments[i].nodes = grub_calloc (node_count, sizeof (*nodes));
|
|
||||||
if (!cache->lv->segments[i].nodes)
|
|
||||||
{
|
|
||||||
for (j = 0; j < i; ++j)
|
|
||||||
grub_free (cache->lv->segments[j].nodes);
|
|
||||||
grub_free (cache->lv->segments);
|
|
||||||
cache->lv->segments = NULL;
|
|
||||||
grub_lvm_free_cache_lvs (cache_lvs);
|
|
||||||
goto fail4;
|
|
||||||
}
|
|
||||||
grub_memcpy (cache->lv->segments[i].nodes, nodes, node_count * sizeof (*nodes));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache->lv->segments)
|
|
||||||
{
|
|
||||||
cache->lv->segment_count = lv->segment_count;
|
|
||||||
cache->lv->vg = vg;
|
|
||||||
cache->lv->next = vg->lvs;
|
|
||||||
vg->lvs = cache->lv;
|
|
||||||
cache->lv = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_lvm_free_cache_lvs (cache_lvs);
|
|
||||||
if (grub_diskfilter_vg_register (vg))
|
if (grub_diskfilter_vg_register (vg))
|
||||||
goto fail4;
|
goto fail4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/diskfilter.h>
|
#include <grub/diskfilter.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -103,6 +104,9 @@ struct grub_raid_super_1x
|
||||||
|
|
||||||
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
|
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
|
||||||
|
|
||||||
|
#define GRUB_MD_SECTOR_SHIFT 9 /* Follow Linux kernel v6.8. */
|
||||||
|
#define GRUB_MD_SECTOR_SIZE (1 << GRUB_MD_SECTOR_SHIFT)
|
||||||
|
|
||||||
static struct grub_diskfilter_vg *
|
static struct grub_diskfilter_vg *
|
||||||
grub_mdraid_detect (grub_disk_t disk,
|
grub_mdraid_detect (grub_disk_t disk,
|
||||||
struct grub_diskfilter_pv_id *id,
|
struct grub_diskfilter_pv_id *id,
|
||||||
|
@ -129,6 +133,7 @@ grub_mdraid_detect (grub_disk_t disk,
|
||||||
grub_uint32_t level;
|
grub_uint32_t level;
|
||||||
struct grub_diskfilter_vg *array;
|
struct grub_diskfilter_vg *array;
|
||||||
char *uuid;
|
char *uuid;
|
||||||
|
grub_uint64_t sb_sz, data_end, sb_end;
|
||||||
|
|
||||||
if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
|
if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -154,6 +159,79 @@ grub_mdraid_detect (grub_disk_t disk,
|
||||||
|| grub_le_to_cpu64 (sb.super_offset) != sector)
|
|| grub_le_to_cpu64 (sb.super_offset) != sector)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The first check follows the Linux kernel's data_size
|
||||||
|
* validation from v6.8-rc5.
|
||||||
|
*/
|
||||||
|
if (grub_le_to_cpu64 (sb.data_size) < 10 ||
|
||||||
|
grub_le_to_cpu64 (sb.raid_disks) > GRUB_MDRAID_MAX_DISKS)
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x", "Corrupted superblock\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total size of superblock: 256 bytes plus 2 bytes per device
|
||||||
|
* in the array.
|
||||||
|
*/
|
||||||
|
sb_sz = sizeof (struct grub_raid_super_1x) + grub_le_to_cpu64 (sb.raid_disks) * 2;
|
||||||
|
|
||||||
|
if (grub_add (grub_le_to_cpu64 (sb.super_offset),
|
||||||
|
(ALIGN_UP(sb_sz, GRUB_MD_SECTOR_SIZE) >> GRUB_MD_SECTOR_SHIFT), &sb_end))
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x", "Invalid superblock end.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_add (grub_le_to_cpu64 (sb.data_offset),
|
||||||
|
grub_le_to_cpu64 (sb.data_size), &data_end))
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x", "Invalid data end.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In minor versions 1 and 2, superblock is positioned before data. */
|
||||||
|
if (minor_version)
|
||||||
|
{
|
||||||
|
if (grub_le_to_cpu64 (sb.data_offset) < sb_end)
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x",
|
||||||
|
"The superblock either overlaps with the data "
|
||||||
|
"or is behind it.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_end > size)
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x",
|
||||||
|
"The data region ends at %" PRIuGRUB_UINT64_T ", "
|
||||||
|
"past the end of the disk (%" PRIuGRUB_UINT64_T ")\n",
|
||||||
|
data_end, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In minor version 0, superblock is at the end of the device. */
|
||||||
|
if (grub_le_to_cpu64 (sb.super_offset) < data_end)
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x",
|
||||||
|
"The data either overlaps with the superblock "
|
||||||
|
"or is behind it.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb_end > size)
|
||||||
|
{
|
||||||
|
grub_dprintf ("mdraid1x",
|
||||||
|
"The superblock region ends at "
|
||||||
|
"%" PRIuGRUB_UINT64_T ", past the end of "
|
||||||
|
"the disk (%" PRIuGRUB_UINT64_T ")\n",
|
||||||
|
sb_end, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sb.major_version != grub_cpu_to_le32_compile_time (1))
|
if (sb.major_version != grub_cpu_to_le32_compile_time (1))
|
||||||
/* Unsupported version. */
|
/* Unsupported version. */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -96,8 +97,14 @@ GRUB_MOD_INIT(memdisk)
|
||||||
|
|
||||||
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
||||||
|
|
||||||
memdisk_size = header->size - sizeof (struct grub_module_header);
|
if (grub_sub (header->size, sizeof (struct grub_module_header), &memdisk_size))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while obtaining memdisk size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
memdisk_addr = grub_malloc (memdisk_size);
|
memdisk_addr = grub_malloc (memdisk_size);
|
||||||
|
if (memdisk_addr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
||||||
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/partition.h>
|
#include <grub/partition.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ plainmount_configure_password (grub_cryptodisk_t dev, const char *hash,
|
||||||
grub_uint8_t *derived_hash, *dh;
|
grub_uint8_t *derived_hash, *dh;
|
||||||
char *p;
|
char *p;
|
||||||
unsigned int round, i, len, size;
|
unsigned int round, i, len, size;
|
||||||
grub_size_t alloc_size;
|
grub_size_t alloc_size, sz;
|
||||||
grub_err_t err = GRUB_ERR_NONE;
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
|
||||||
/* Support none (plain) hash */
|
/* Support none (plain) hash */
|
||||||
|
@ -145,7 +146,11 @@ plainmount_configure_password (grub_cryptodisk_t dev, const char *hash,
|
||||||
* Allocate buffer for the password and for an added prefix character
|
* Allocate buffer for the password and for an added prefix character
|
||||||
* for each hash round ('alloc_size' may not be a multiple of 'len').
|
* for each hash round ('alloc_size' may not be a multiple of 'len').
|
||||||
*/
|
*/
|
||||||
p = grub_zalloc (alloc_size + (alloc_size / len) + 1);
|
if (grub_add (alloc_size, (alloc_size / len), &sz) ||
|
||||||
|
grub_add (sz, 1, &sz))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while allocating size of password buffer"));
|
||||||
|
|
||||||
|
p = grub_zalloc (sz);
|
||||||
derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
|
derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
|
||||||
if (p == NULL || derived_hash == NULL)
|
if (p == NULL || derived_hash == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
depends bli part_gpt
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -703,11 +704,16 @@ static struct grub_fs grub_affs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(affs)
|
GRUB_MOD_INIT(affs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_affs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_affs_fs);
|
grub_fs_register (&grub_affs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(affs)
|
GRUB_MOD_FINI(affs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_affs_fs);
|
grub_fs_unregister (&grub_affs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <grub/fs.h>
|
#include <grub/fs.h>
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ handle_symlink (struct grub_archelp_data *data,
|
||||||
char *rest;
|
char *rest;
|
||||||
char *linktarget;
|
char *linktarget;
|
||||||
grub_size_t linktarget_len;
|
grub_size_t linktarget_len;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
*restart = 0;
|
*restart = 0;
|
||||||
|
|
||||||
|
@ -98,7 +100,12 @@ handle_symlink (struct grub_archelp_data *data,
|
||||||
if (linktarget[0] == '\0')
|
if (linktarget[0] == '\0')
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
linktarget_len = grub_strlen (linktarget);
|
linktarget_len = grub_strlen (linktarget);
|
||||||
target = grub_malloc (linktarget_len + grub_strlen (*name) + 2);
|
|
||||||
|
if (grub_add (linktarget_len, grub_strlen (*name), &sz) ||
|
||||||
|
grub_add (sz, 2, &sz))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("link target length overflow"));
|
||||||
|
|
||||||
|
target = grub_malloc (sz);
|
||||||
if (!target)
|
if (!target)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -808,7 +809,7 @@ find_file (const char *path, grub_disk_t disk,
|
||||||
.disk = disk,
|
.disk = disk,
|
||||||
.sb = sb,
|
.sb = sb,
|
||||||
};
|
};
|
||||||
struct grub_fshelp_node *found;
|
struct grub_fshelp_node *found = NULL;
|
||||||
|
|
||||||
err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino,
|
err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino,
|
||||||
sizeof (root.ino));
|
sizeof (root.ino));
|
||||||
|
@ -1106,7 +1107,11 @@ GRUB_MOD_INIT (bfs)
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
|
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
|
||||||
sizeof (struct grub_bfs_extent));
|
sizeof (struct grub_bfs_extent));
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_bfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_bfs_fs);
|
grub_fs_register (&grub_bfs_fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODE_AFS
|
#ifdef MODE_AFS
|
||||||
|
@ -1115,5 +1120,6 @@ GRUB_MOD_FINI (afs)
|
||||||
GRUB_MOD_FINI (bfs)
|
GRUB_MOD_FINI (bfs)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_bfs_fs);
|
grub_fs_unregister (&grub_bfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1276,8 +1276,8 @@ grub_btrfs_mount (grub_device_t dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
data->n_devices_allocated = 16;
|
data->n_devices_allocated = 16;
|
||||||
data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
data->devices_attached = grub_calloc (data->n_devices_allocated,
|
||||||
* data->n_devices_allocated);
|
sizeof (data->devices_attached[0]));
|
||||||
if (!data->devices_attached)
|
if (!data->devices_attached)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
@ -1538,7 +1538,10 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
err = lower_bound (data, &key_in, &key_out, tree,
|
err = lower_bound (data, &key_in, &key_out, tree,
|
||||||
&elemaddr, &elemsize, &desc, 0);
|
&elemaddr, &elemsize, &desc, 0);
|
||||||
if (err)
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (desc.data);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (key_out.object_id != ino
|
if (key_out.object_id != ino
|
||||||
|| key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM)
|
|| key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM)
|
||||||
{
|
{
|
||||||
|
@ -1801,6 +1804,7 @@ find_path (struct grub_btrfs_data *data,
|
||||||
char *path_alloc = NULL;
|
char *path_alloc = NULL;
|
||||||
char *origpath = NULL;
|
char *origpath = NULL;
|
||||||
unsigned symlinks_max = 32;
|
unsigned symlinks_max = 32;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
err = get_root (data, key, tree, type);
|
err = get_root (data, key, tree, type);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1891,9 +1895,15 @@ find_path (struct grub_btrfs_data *data,
|
||||||
struct grub_btrfs_dir_item *cdirel;
|
struct grub_btrfs_dir_item *cdirel;
|
||||||
if (elemsize > allocated)
|
if (elemsize > allocated)
|
||||||
{
|
{
|
||||||
allocated = 2 * elemsize;
|
if (grub_mul (2, elemsize, &allocated) ||
|
||||||
|
grub_add (allocated, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_free (path_alloc);
|
||||||
|
grub_free (origpath);
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory item size overflow"));
|
||||||
|
}
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
direl = grub_malloc (allocated + 1);
|
direl = grub_malloc (sz);
|
||||||
if (!direl)
|
if (!direl)
|
||||||
{
|
{
|
||||||
grub_free (path_alloc);
|
grub_free (path_alloc);
|
||||||
|
@ -1955,8 +1965,16 @@ find_path (struct grub_btrfs_data *data,
|
||||||
grub_free (origpath);
|
grub_free (origpath);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
tmp = grub_malloc (grub_le_to_cpu64 (inode.size)
|
|
||||||
+ grub_strlen (path) + 1);
|
if (grub_add (grub_le_to_cpu64 (inode.size), grub_strlen (path), &sz) ||
|
||||||
|
grub_add (sz, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_free (direl);
|
||||||
|
grub_free (path_alloc);
|
||||||
|
grub_free (origpath);
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
|
||||||
|
}
|
||||||
|
tmp = grub_malloc (sz);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
{
|
{
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
|
@ -2078,6 +2096,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
grub_uint64_t tree;
|
grub_uint64_t tree;
|
||||||
grub_uint8_t type;
|
grub_uint8_t type;
|
||||||
grub_size_t est_size = 0;
|
grub_size_t est_size = 0;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -2099,6 +2118,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_btrfs_unmount (data);
|
grub_btrfs_unmount (data);
|
||||||
|
grub_free (desc.data);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|
||||||
|
@ -2119,9 +2139,15 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
}
|
}
|
||||||
if (elemsize > allocated)
|
if (elemsize > allocated)
|
||||||
{
|
{
|
||||||
allocated = 2 * elemsize;
|
if (grub_mul (2, elemsize, &allocated) ||
|
||||||
|
grub_add (allocated, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory element size overflow"));
|
||||||
|
r = -grub_errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
direl = grub_malloc (allocated + 1);
|
direl = grub_malloc (sz);
|
||||||
if (!direl)
|
if (!direl)
|
||||||
{
|
{
|
||||||
r = -grub_errno;
|
r = -grub_errno;
|
||||||
|
@ -2413,6 +2439,7 @@ static struct grub_fs grub_btrfs_fs = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (btrfs)
|
GRUB_MOD_INIT (btrfs)
|
||||||
{
|
{
|
||||||
|
grub_btrfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_btrfs_fs);
|
grub_fs_register (&grub_btrfs_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/cbfs_core.h>
|
#include <grub/cbfs_core.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -390,11 +391,16 @@ GRUB_MOD_INIT (cbfs)
|
||||||
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
||||||
init_cbfsdisk ();
|
init_cbfsdisk ();
|
||||||
#endif
|
#endif
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_cbfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cbfs_fs);
|
grub_fs_register (&grub_cbfs_fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (cbfs)
|
GRUB_MOD_FINI (cbfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_cbfs_fs);
|
grub_fs_unregister (&grub_cbfs_fs);
|
||||||
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
|
||||||
fini_cbfsdisk ();
|
fini_cbfsdisk ();
|
||||||
|
|
|
@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
|
||||||
|
|
||||||
GRUB_MOD_INIT (cpio)
|
GRUB_MOD_INIT (cpio)
|
||||||
{
|
{
|
||||||
|
grub_cpio_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cpio_fs);
|
grub_fs_register (&grub_cpio_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
|
||||||
|
|
||||||
GRUB_MOD_INIT (cpio_be)
|
GRUB_MOD_INIT (cpio_be)
|
||||||
{
|
{
|
||||||
|
grub_cpio_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cpio_fs);
|
grub_fs_register (&grub_cpio_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/archelp.h>
|
#include <grub/archelp.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
struct head hd;
|
struct head hd;
|
||||||
grub_size_t namesize;
|
grub_size_t namesize;
|
||||||
grub_uint32_t modeval;
|
grub_uint32_t modeval;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
data->hofs = data->next_hofs;
|
data->hofs = data->next_hofs;
|
||||||
|
|
||||||
|
@ -60,11 +62,21 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
||||||
data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
|
|
||||||
|
if (grub_cast (read_number (hd.filesize, ARRAY_SIZE (hd.filesize)), &data->size))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow"));
|
||||||
|
|
||||||
if (mtime)
|
if (mtime)
|
||||||
*mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
|
{
|
||||||
modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
|
if (grub_cast (read_number (hd.mtime, ARRAY_SIZE (hd.mtime)), mtime))
|
||||||
namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
|
return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_cast (read_number (hd.mode, ARRAY_SIZE (hd.mode)), &modeval))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow"));
|
||||||
|
|
||||||
|
if (grub_cast (read_number (hd.namesize, ARRAY_SIZE (hd.namesize)), &namesize))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("namesize overflow"));
|
||||||
|
|
||||||
/* Don't allow negative numbers. */
|
/* Don't allow negative numbers. */
|
||||||
if (namesize >= 0x80000000)
|
if (namesize >= 0x80000000)
|
||||||
|
@ -76,7 +88,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
|
|
||||||
*mode = modeval;
|
*mode = modeval;
|
||||||
|
|
||||||
*name = grub_malloc (namesize + 1);
|
if (grub_add (namesize, 1, &sz))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("file name size overflow"));
|
||||||
|
|
||||||
|
*name = grub_malloc (sz);
|
||||||
if (*name == NULL)
|
if (*name == NULL)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
@ -110,10 +125,17 @@ grub_cpio_get_link_target (struct grub_archelp_data *data)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (data->size == 0)
|
if (data->size == 0)
|
||||||
return grub_strdup ("");
|
return grub_strdup ("");
|
||||||
ret = grub_malloc (data->size + 1);
|
|
||||||
|
if (grub_add (data->size, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("target data size overflow"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = grub_malloc (sz);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
1006
grub-core/fs/erofs.c
Normal file
1006
grub-core/fs/erofs.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -495,6 +495,11 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
struct grub_ext4_extent *ext;
|
struct grub_ext4_extent *ext;
|
||||||
int i;
|
int i;
|
||||||
grub_disk_addr_t ret;
|
grub_disk_addr_t ret;
|
||||||
|
grub_uint16_t nent;
|
||||||
|
/* Maximum number of extent entries in the inode's inline extent area. */
|
||||||
|
const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */
|
||||||
|
/* Maximum number of extent entries in the external extent block. */
|
||||||
|
const grub_uint16_t max_external_ext = EXT2_BLOCK_SIZE (data) / sizeof (*ext) - 1; /* Minus 1 extent header. */
|
||||||
|
|
||||||
if (grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
|
if (grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
|
||||||
fileblock, &leaf) != GRUB_ERR_NONE)
|
fileblock, &leaf) != GRUB_ERR_NONE)
|
||||||
|
@ -508,7 +513,23 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ext = (struct grub_ext4_extent *) (leaf + 1);
|
ext = (struct grub_ext4_extent *) (leaf + 1);
|
||||||
for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
|
|
||||||
|
nent = grub_le_to_cpu16 (leaf->entries);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the effective number of extent entries (nent) to process.
|
||||||
|
* If the extent header (leaf) is stored inline in the inode’s block
|
||||||
|
* area, i.e. at inode->blocks.dir_blocks, then only max_inline_ext
|
||||||
|
* entries can fit. Otherwise, if the header was read from an external
|
||||||
|
* extent block use the larger limit, max_external_ext, based on the
|
||||||
|
* full block size.
|
||||||
|
*/
|
||||||
|
if (leaf == (struct grub_ext4_extent_header *) inode->blocks.dir_blocks)
|
||||||
|
nent = grub_min (nent, max_inline_ext);
|
||||||
|
else
|
||||||
|
nent = grub_min (nent, max_external_ext);
|
||||||
|
|
||||||
|
for (i = 0; i < nent; i++)
|
||||||
{
|
{
|
||||||
if (fileblock < grub_le_to_cpu32 (ext[i].block))
|
if (fileblock < grub_le_to_cpu32 (ext[i].block))
|
||||||
break;
|
break;
|
||||||
|
@ -1123,6 +1144,7 @@ static struct grub_fs grub_ext2_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(ext2)
|
GRUB_MOD_INIT(ext2)
|
||||||
{
|
{
|
||||||
|
grub_ext2_fs.mod = mod;
|
||||||
grub_fs_register (&grub_ext2_fs);
|
grub_fs_register (&grub_ext2_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -872,6 +873,9 @@ grub_f2fs_mount (grub_disk_t disk)
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if (grub_errno == GRUB_ERR_NONE)
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "not a F2FS filesystem");
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -955,6 +959,7 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
|
||||||
char *symlink;
|
char *symlink;
|
||||||
struct grub_fshelp_node *diro = node;
|
struct grub_fshelp_node *diro = node;
|
||||||
grub_uint64_t filesize;
|
grub_uint64_t filesize;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (!diro->inode_read)
|
if (!diro->inode_read)
|
||||||
{
|
{
|
||||||
|
@ -965,7 +970,12 @@ grub_f2fs_read_symlink (grub_fshelp_node_t node)
|
||||||
|
|
||||||
filesize = grub_f2fs_file_size(&diro->inode.i);
|
filesize = grub_f2fs_file_size(&diro->inode.i);
|
||||||
|
|
||||||
symlink = grub_malloc (filesize + 1);
|
if (grub_add (filesize, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
symlink = grub_malloc (sz);
|
||||||
if (!symlink)
|
if (!symlink)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -994,6 +1004,7 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
|
||||||
enum FILE_TYPE ftype;
|
enum FILE_TYPE ftype;
|
||||||
int name_len;
|
int name_len;
|
||||||
int ret;
|
int ret;
|
||||||
|
int sz;
|
||||||
|
|
||||||
if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
|
if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
|
||||||
{
|
{
|
||||||
|
@ -1007,7 +1018,12 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
|
||||||
if (name_len >= F2FS_NAME_LEN)
|
if (name_len >= F2FS_NAME_LEN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
filename = grub_malloc (name_len + 1);
|
if (grub_add (name_len, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory entry name length overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
filename = grub_malloc (sz);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1350,6 +1366,7 @@ static struct grub_fs grub_f2fs_fs = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (f2fs)
|
GRUB_MOD_INIT (f2fs)
|
||||||
{
|
{
|
||||||
|
grub_f2fs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_f2fs_fs);
|
grub_fs_register (&grub_f2fs_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1312,6 +1312,7 @@ GRUB_MOD_INIT(fat)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
|
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
|
||||||
|
grub_fat_fs.mod = mod;
|
||||||
grub_fs_register (&grub_fat_fs);
|
grub_fs_register (&grub_fat_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,10 @@ find_file (char *currpath,
|
||||||
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||||
N_("too deep nesting of symlinks"));
|
N_("too deep nesting of symlinks"));
|
||||||
|
|
||||||
|
if (read_symlink != NULL)
|
||||||
symlink = read_symlink (ctx->currnode->node);
|
symlink = read_symlink (ctx->currnode->node);
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "read_symlink is NULL");
|
||||||
|
|
||||||
if (!symlink)
|
if (!symlink)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
|
@ -379,7 +379,7 @@ grub_hfs_mount (grub_disk_t disk)
|
||||||
volume name. */
|
volume name. */
|
||||||
key.parent_dir = grub_cpu_to_be32_compile_time (1);
|
key.parent_dir = grub_cpu_to_be32_compile_time (1);
|
||||||
key.strlen = data->sblock.volname[0];
|
key.strlen = data->sblock.volname[0];
|
||||||
grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
|
grub_strlcpy ((char *) key.str, (char *) (data->sblock.volname + 1), sizeof (key.str));
|
||||||
|
|
||||||
if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
|
if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
|
||||||
0, (char *) &dir, sizeof (dir)) == 0)
|
0, (char *) &dir, sizeof (dir)) == 0)
|
||||||
|
@ -1434,6 +1434,7 @@ static struct grub_fs grub_hfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(hfs)
|
GRUB_MOD_INIT(hfs)
|
||||||
{
|
{
|
||||||
|
grub_hfs_fs.mod = mod;
|
||||||
if (!grub_is_lockdown ())
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_register (&grub_hfs_fs);
|
grub_fs_register (&grub_hfs_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
|
|
|
@ -405,7 +405,7 @@ grub_hfsplus_mount (grub_disk_t disk)
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
|
||||||
grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
|
grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
@ -1176,6 +1176,7 @@ static struct grub_fs grub_hfsplus_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(hfsplus)
|
GRUB_MOD_INIT(hfsplus)
|
||||||
{
|
{
|
||||||
|
grub_hfsplus_fs.mod = mod;
|
||||||
grub_fs_register (&grub_hfsplus_fs);
|
grub_fs_register (&grub_hfsplus_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,14 +244,19 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
node->compress_index_size = grub_le_to_cpu32 (index_size);
|
node->compress_index_size = grub_le_to_cpu32 (index_size);
|
||||||
node->compress_index = grub_malloc (node->compress_index_size
|
node->compress_index = grub_calloc (node->compress_index_size,
|
||||||
* sizeof (node->compress_index[0]));
|
sizeof (node->compress_index[0]));
|
||||||
if (!node->compress_index)
|
if (!node->compress_index)
|
||||||
{
|
{
|
||||||
node->compressed = 0;
|
node->compressed = 0;
|
||||||
grub_free (attr_node);
|
grub_free (attr_node);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The node->compress_index_size * sizeof (node->compress_index[0]) is safe here
|
||||||
|
* due to relevant checks done in grub_calloc() above.
|
||||||
|
*/
|
||||||
if (grub_hfsplus_read_file (node, 0, 0,
|
if (grub_hfsplus_read_file (node, 0, 0,
|
||||||
0x104 + sizeof (index_size),
|
0x104 + sizeof (index_size),
|
||||||
node->compress_index_size
|
node->compress_index_size
|
||||||
|
|
|
@ -551,6 +551,9 @@ grub_iso9660_mount (grub_disk_t disk)
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if (grub_errno == GRUB_ERR_NONE)
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -625,9 +628,19 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||||
filename type is stored. */
|
filename type is stored. */
|
||||||
/* FIXME: Fix this slightly improper cast. */
|
/* FIXME: Fix this slightly improper cast. */
|
||||||
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
|
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
|
||||||
|
{
|
||||||
|
if (ctx->filename_alloc)
|
||||||
|
grub_free (ctx->filename);
|
||||||
|
ctx->filename_alloc = 0;
|
||||||
ctx->filename = (char *) ".";
|
ctx->filename = (char *) ".";
|
||||||
|
}
|
||||||
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
|
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
|
||||||
|
{
|
||||||
|
if (ctx->filename_alloc)
|
||||||
|
grub_free (ctx->filename);
|
||||||
|
ctx->filename_alloc = 0;
|
||||||
ctx->filename = (char *) "..";
|
ctx->filename = (char *) "..";
|
||||||
|
}
|
||||||
else if (entry->len >= 5)
|
else if (entry->len >= 5)
|
||||||
{
|
{
|
||||||
grub_size_t off = 0, csize = 1;
|
grub_size_t off = 0, csize = 1;
|
||||||
|
@ -1247,6 +1260,7 @@ static struct grub_fs grub_iso9660_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(iso9660)
|
GRUB_MOD_INIT(iso9660)
|
||||||
{
|
{
|
||||||
|
grub_iso9660_fs.mod = mod;
|
||||||
grub_fs_register (&grub_iso9660_fs);
|
grub_fs_register (&grub_iso9660_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -41,6 +42,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
#define GRUB_JFS_TREE_LEAF 2
|
#define GRUB_JFS_TREE_LEAF 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define max entries stored in-line in an inode.
|
||||||
|
* https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||||||
|
*/
|
||||||
|
#define GRUB_JFS_INODE_INLINE_ENTRIES 8
|
||||||
|
#define GRUB_JFS_DIR_MAX_SLOTS 128
|
||||||
|
|
||||||
struct grub_jfs_sblock
|
struct grub_jfs_sblock
|
||||||
{
|
{
|
||||||
/* The magic for JFS. It should contain the string "JFS1". */
|
/* The magic for JFS. It should contain the string "JFS1". */
|
||||||
|
@ -203,9 +211,9 @@ struct grub_jfs_inode
|
||||||
grub_uint8_t freecnt;
|
grub_uint8_t freecnt;
|
||||||
grub_uint8_t freelist;
|
grub_uint8_t freelist;
|
||||||
grub_uint32_t idotdot;
|
grub_uint32_t idotdot;
|
||||||
grub_uint8_t sorted[8];
|
grub_uint8_t sorted[GRUB_JFS_INODE_INLINE_ENTRIES];
|
||||||
} header;
|
} header;
|
||||||
struct grub_jfs_leaf_dirent dirents[8];
|
struct grub_jfs_leaf_dirent dirents[GRUB_JFS_INODE_INLINE_ENTRIES];
|
||||||
} GRUB_PACKED dir;
|
} GRUB_PACKED dir;
|
||||||
/* Fast symlink. */
|
/* Fast symlink. */
|
||||||
struct
|
struct
|
||||||
|
@ -258,7 +266,21 @@ static grub_dl_t my_mod;
|
||||||
|
|
||||||
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
|
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
|
||||||
|
|
||||||
static grub_int64_t
|
/*
|
||||||
|
* An extent's offset, physical and logical, is represented as a 40-bit value.
|
||||||
|
* This 40-bit value is split into two parts:
|
||||||
|
* - offset1: the most signficant 8 bits of the offset,
|
||||||
|
* - offset2: the least significant 32 bits of the offset.
|
||||||
|
*
|
||||||
|
* This function calculates and returns the 64-bit offset of an extent.
|
||||||
|
*/
|
||||||
|
static grub_uint64_t
|
||||||
|
get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
|
||||||
|
{
|
||||||
|
return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_uint64_t
|
||||||
getblk (struct grub_jfs_treehead *treehead,
|
getblk (struct grub_jfs_treehead *treehead,
|
||||||
struct grub_jfs_tree_extent *extents,
|
struct grub_jfs_tree_extent *extents,
|
||||||
int max_extents,
|
int max_extents,
|
||||||
|
@ -267,28 +289,33 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||||
{
|
{
|
||||||
int found = -1;
|
int found = -1;
|
||||||
int i;
|
int i;
|
||||||
|
grub_uint64_t ext_offset, ext_blk;
|
||||||
|
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
|
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
|
||||||
i < max_extents; i++)
|
i < max_extents; i++)
|
||||||
{
|
{
|
||||||
|
ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2);
|
||||||
|
ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2);
|
||||||
|
|
||||||
if (treehead->flags & GRUB_JFS_TREE_LEAF)
|
if (treehead->flags & GRUB_JFS_TREE_LEAF)
|
||||||
{
|
{
|
||||||
/* Read the leafnode. */
|
/* Read the leafnode. */
|
||||||
if (grub_le_to_cpu32 (extents[i].offset2) <= blk
|
if (ext_offset <= blk
|
||||||
&& ((grub_le_to_cpu16 (extents[i].extent.length))
|
&& ((grub_le_to_cpu16 (extents[i].extent.length))
|
||||||
+ (extents[i].extent.length2 << 16)
|
+ (extents[i].extent.length2 << 16)
|
||||||
+ grub_le_to_cpu32 (extents[i].offset2)) > blk)
|
+ ext_offset) > blk)
|
||||||
return (blk - grub_le_to_cpu32 (extents[i].offset2)
|
return (blk - ext_offset + ext_blk);
|
||||||
+ grub_le_to_cpu32 (extents[i].extent.blk2));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (blk >= grub_le_to_cpu32 (extents[i].offset2))
|
if (blk >= ext_offset)
|
||||||
found = i;
|
found = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found != -1)
|
if (found != -1)
|
||||||
{
|
{
|
||||||
grub_int64_t ret = -1;
|
grub_uint64_t ret = 0;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct grub_jfs_treehead treehead;
|
struct grub_jfs_treehead treehead;
|
||||||
|
@ -297,13 +324,12 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||||
|
|
||||||
tree = grub_zalloc (sizeof (*tree));
|
tree = grub_zalloc (sizeof (*tree));
|
||||||
if (!tree)
|
if (!tree)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
if (!grub_disk_read (data->disk,
|
if (!grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
|
(grub_disk_addr_t) ext_blk
|
||||||
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
<< (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS),
|
||||||
- GRUB_DISK_SECTOR_BITS), 0,
|
0, sizeof (*tree), (char *) tree))
|
||||||
sizeof (*tree), (char *) tree))
|
|
||||||
{
|
{
|
||||||
if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
|
if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
|
||||||
grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
|
grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
|
||||||
|
@ -311,19 +337,20 @@ getblk (struct grub_jfs_treehead *treehead,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected");
|
grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected");
|
||||||
ret = -1;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grub_free (tree);
|
grub_free (tree);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
grub_error (GRUB_ERR_READ_ERROR, "jfs: block %" PRIuGRUB_UINT64_T " not found", blk);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the block number for the block BLK in the node INODE in the
|
/* Get the block number for the block BLK in the node INODE in the
|
||||||
mounted filesystem DATA. */
|
mounted filesystem DATA. */
|
||||||
static grub_int64_t
|
static grub_uint64_t
|
||||||
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
|
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
|
||||||
grub_uint64_t blk)
|
grub_uint64_t blk)
|
||||||
{
|
{
|
||||||
|
@ -354,7 +381,7 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino,
|
||||||
sizeof (iag_inodes), &iag_inodes))
|
sizeof (iag_inodes), &iag_inodes))
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2);
|
inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2);
|
||||||
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||||||
- GRUB_DISK_SECTOR_BITS);
|
- GRUB_DISK_SECTOR_BITS);
|
||||||
inoblk += inonum;
|
inoblk += inonum;
|
||||||
|
@ -453,6 +480,13 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||||
/* Check if the entire tree is contained within the inode. */
|
/* Check if the entire tree is contained within the inode. */
|
||||||
if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
|
if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
|
||||||
{
|
{
|
||||||
|
if (inode->dir.header.count > GRUB_JFS_INODE_INLINE_ENTRIES)
|
||||||
|
{
|
||||||
|
grub_free (diro);
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, N_("invalid JFS inode"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
diro->leaf = inode->dir.dirents;
|
diro->leaf = inode->dir.dirents;
|
||||||
diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
|
diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
|
||||||
diro->sorted = inode->dir.header.sorted;
|
diro->sorted = inode->dir.header.sorted;
|
||||||
|
@ -468,7 +502,16 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
|
if (inode->dir.header.sorted[0] >= GRUB_JFS_DIR_MAX_SLOTS)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, N_("invalid directory slot index"));
|
||||||
|
grub_free (diro->dirpage);
|
||||||
|
grub_free (diro);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1,
|
||||||
|
de[inode->dir.header.sorted[0]].ex.blk2);
|
||||||
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
|
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
|
||||||
|
|
||||||
/* Read in the nodes until we are on the leaf node level. */
|
/* Read in the nodes until we are on the leaf node level. */
|
||||||
|
@ -486,7 +529,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||||||
|
|
||||||
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
|
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
|
||||||
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
|
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
|
||||||
blk = (grub_le_to_cpu32 (de[index].ex.blk2)
|
blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2)
|
||||||
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||||||
- GRUB_DISK_SECTOR_BITS));
|
- GRUB_DISK_SECTOR_BITS));
|
||||||
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
|
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
|
||||||
|
@ -716,7 +759,6 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path,
|
||||||
grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode);
|
grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode);
|
||||||
|
|
||||||
grub_jfs_closedir (diro);
|
grub_jfs_closedir (diro);
|
||||||
diro = 0;
|
|
||||||
|
|
||||||
if (grub_jfs_read_inode (data, ino, &data->currinode))
|
if (grub_jfs_read_inode (data, ino, &data->currinode))
|
||||||
break;
|
break;
|
||||||
|
@ -963,11 +1005,16 @@ static struct grub_fs grub_jfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(jfs)
|
GRUB_MOD_INIT(jfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_jfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_jfs_fs);
|
grub_fs_register (&grub_jfs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(jfs)
|
GRUB_MOD_FINI(jfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_jfs_fs);
|
grub_fs_unregister (&grub_jfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -734,7 +735,11 @@ GRUB_MOD_INIT(minix)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_minix_fs.mod = mod;
|
||||||
grub_fs_register (&grub_minix_fs);
|
grub_fs_register (&grub_minix_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,5 +761,6 @@ GRUB_MOD_FINI(minix)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_minix_fs);
|
grub_fs_unregister (&grub_minix_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ read_number (const char *str, grub_size_t size)
|
||||||
|
|
||||||
GRUB_MOD_INIT (newc)
|
GRUB_MOD_INIT (newc)
|
||||||
{
|
{
|
||||||
|
grub_cpio_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cpio_fs);
|
grub_fs_register (&grub_cpio_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -1231,11 +1232,16 @@ GRUB_MOD_INIT (nilfs2)
|
||||||
grub_nilfs2_dat_entry));
|
grub_nilfs2_dat_entry));
|
||||||
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
|
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
|
||||||
== sizeof (struct grub_nilfs2_inode));
|
== sizeof (struct grub_nilfs2_inode));
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_nilfs2_fs.mod = mod;
|
||||||
grub_fs_register (&grub_nilfs2_fs);
|
grub_fs_register (&grub_nilfs2_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (nilfs2)
|
GRUB_MOD_FINI (nilfs2)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_nilfs2_fs);
|
grub_fs_unregister (&grub_nilfs2_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
#include <grub/ntfs.h>
|
#include <grub/ntfs.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -70,6 +71,175 @@ res_attr_data_len (void *res_attr_ptr)
|
||||||
return u32at (res_attr_ptr, 0x10);
|
return u32at (res_attr_ptr, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the attribute is valid and doesn't exceed the allocated region.
|
||||||
|
* This accounts for resident and non-resident data.
|
||||||
|
*
|
||||||
|
* This is based off the documentation from the linux-ntfs project:
|
||||||
|
* https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
validate_attribute (grub_uint8_t *attr, void *end)
|
||||||
|
{
|
||||||
|
grub_size_t attr_size = 0;
|
||||||
|
grub_size_t min_size = 0;
|
||||||
|
grub_size_t run_size = 0;
|
||||||
|
grub_size_t spare = (grub_uint8_t *) end - attr;
|
||||||
|
/*
|
||||||
|
* Just used as a temporary variable to try and deal with cases where someone
|
||||||
|
* tries to overlap fields.
|
||||||
|
*/
|
||||||
|
grub_size_t curr = 0;
|
||||||
|
|
||||||
|
/* Need verify we can entirely read the attributes header. */
|
||||||
|
if (attr + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* So, the rest of this code uses a 16bit int for the attribute length but
|
||||||
|
* from reading the all the documentation I could find it says this field is
|
||||||
|
* actually 32bit. But let's be consistent with the rest of the code.
|
||||||
|
*
|
||||||
|
* https://elixir.bootlin.com/linux/v6.10.7/source/fs/ntfs3/ntfs.h#L370
|
||||||
|
*/
|
||||||
|
attr_size = u16at (attr, GRUB_NTFS_ATTRIBUTE_LENGTH);
|
||||||
|
|
||||||
|
if (attr_size > spare)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Not an error case, just reached the end of the attributes. */
|
||||||
|
if (attr_size == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extra validation by trying to calculate a minimum possible size for this
|
||||||
|
* attribute. +8 from the size of the resident data struct which is the
|
||||||
|
* minimum that can be added.
|
||||||
|
*/
|
||||||
|
min_size = GRUB_NTFS_ATTRIBUTE_HEADER_SIZE + 8;
|
||||||
|
|
||||||
|
if (min_size > attr_size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Is the data is resident (0) or not (1). */
|
||||||
|
if (attr[GRUB_NTFS_ATTRIBUTE_RESIDENT] == 0)
|
||||||
|
{
|
||||||
|
/* Read the offset and size of the attribute. */
|
||||||
|
curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_RES_OFFSET);
|
||||||
|
curr += u32at (attr, GRUB_NTFS_ATTRIBUTE_RES_LENGTH);
|
||||||
|
if (curr > min_size)
|
||||||
|
min_size = curr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the data is non-resident, the minimum size is 64 which is where
|
||||||
|
* the data runs start. We already have a minimum size of 24. So, just
|
||||||
|
* adding 40 to get to the real value.
|
||||||
|
*/
|
||||||
|
min_size += 40;
|
||||||
|
if (min_size > attr_size)
|
||||||
|
goto fail;
|
||||||
|
/* If the compression unit size is > 0, +8 bytes*/
|
||||||
|
if (u16at (attr, GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE) > 0)
|
||||||
|
min_size += 8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to consider the data runs now. Each member of the run has byte
|
||||||
|
* that describes the size of the data length and offset. Each being
|
||||||
|
* 4 bits in the byte.
|
||||||
|
*/
|
||||||
|
curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_DATA_RUNS);
|
||||||
|
|
||||||
|
if (curr + 1 > min_size)
|
||||||
|
min_size = curr + 1;
|
||||||
|
|
||||||
|
if (min_size > attr_size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each attribute can store multiple data runs which are stored
|
||||||
|
* continuously in the attribute. They exist as one header byte
|
||||||
|
* with up to 14 bytes following it depending on the lengths.
|
||||||
|
* We stop when we hit a header that is just a NUL byte.
|
||||||
|
*
|
||||||
|
* https://flatcap.github.io/linux-ntfs/ntfs/concepts/data_runs.html
|
||||||
|
*/
|
||||||
|
while (attr[curr] != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We stop when we hit a header that is just a NUL byte. The data
|
||||||
|
* run header is stored as a single byte where the top 4 bits refer
|
||||||
|
* to the number of bytes used to store the total length of the
|
||||||
|
* data run, and the number of bytes used to store the offset.
|
||||||
|
* These directly follow the header byte, so we use them to update
|
||||||
|
* the minimum size. Increment by one more than run size to move on
|
||||||
|
* to the next run size header byte. An example is a run size field
|
||||||
|
* value of 0x32, 3 + 2 = 5 bytes follow the run size. Increment
|
||||||
|
* by 5 to get to the end of this data run then one more to get to
|
||||||
|
* the start of the next run size byte.
|
||||||
|
*/
|
||||||
|
run_size = (attr[curr] & 0x7) + ((attr[curr] >> 4) & 0x7);
|
||||||
|
curr += (run_size + 1);
|
||||||
|
min_size += (run_size + 1);
|
||||||
|
if (min_size > attr_size)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name offset, doing this after data residence checks. */
|
||||||
|
if (u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET) != 0)
|
||||||
|
{
|
||||||
|
curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET);
|
||||||
|
/*
|
||||||
|
* Multiple the name length by 2 as its UTF-16. Can be zero if this in an
|
||||||
|
* unamed attribute.
|
||||||
|
*/
|
||||||
|
curr += attr[GRUB_NTFS_ATTRIBUTE_NAME_LENGTH] * 2;
|
||||||
|
if (curr > min_size)
|
||||||
|
min_size = curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padded to 8 bytes. */
|
||||||
|
if (min_size % 8 != 0)
|
||||||
|
min_size += 8 - (min_size % 8);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point min_size should be exactly attr_size but being flexible
|
||||||
|
* here to avoid any issues.
|
||||||
|
*/
|
||||||
|
if (min_size > attr_size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
grub_dprintf ("ntfs", "spare=%" PRIuGRUB_SIZE " min_size=%" PRIuGRUB_SIZE " attr_size=%" PRIuGRUB_SIZE "\n",
|
||||||
|
spare, min_size, attr_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the next attribute if it exists, otherwise return NULL. */
|
||||||
|
static grub_uint8_t *
|
||||||
|
next_attribute (grub_uint8_t *curr_attribute, void *end, bool validate)
|
||||||
|
{
|
||||||
|
grub_uint8_t *next = curr_attribute;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to verify we aren't exceeding the end of the buffer by reading the
|
||||||
|
* header for the current attribute
|
||||||
|
*/
|
||||||
|
if (curr_attribute + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
next += u16at (curr_attribute, 4);
|
||||||
|
if (validate && validate_attribute (next, end) == false)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
grub_ntfscomp_func_t grub_ntfscomp_func;
|
grub_ntfscomp_func_t grub_ntfscomp_func;
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -78,6 +248,7 @@ fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic)
|
||||||
grub_uint16_t ss;
|
grub_uint16_t ss;
|
||||||
grub_uint8_t *pu;
|
grub_uint8_t *pu;
|
||||||
grub_uint16_t us;
|
grub_uint16_t us;
|
||||||
|
grub_uint16_t pu_offset;
|
||||||
|
|
||||||
COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE);
|
COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE);
|
||||||
|
|
||||||
|
@ -87,7 +258,10 @@ fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic)
|
||||||
ss = u16at (buf, 6) - 1;
|
ss = u16at (buf, 6) - 1;
|
||||||
if (ss != len)
|
if (ss != len)
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "size not match");
|
return grub_error (GRUB_ERR_BAD_FS, "size not match");
|
||||||
pu = buf + u16at (buf, 4);
|
pu_offset = u16at (buf, 4);
|
||||||
|
if (pu_offset >= (len * GRUB_DISK_SECTOR_SIZE - (2 * ss)))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "pu offset size incorrect");
|
||||||
|
pu = buf + pu_offset;
|
||||||
us = u16at (pu, 0);
|
us = u16at (pu, 0);
|
||||||
buf -= 2;
|
buf -= 2;
|
||||||
while (ss > 0)
|
while (ss > 0)
|
||||||
|
@ -119,13 +293,20 @@ static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
|
||||||
grub_disk_read_hook_t read_hook,
|
grub_disk_read_hook_t read_hook,
|
||||||
void *read_hook_data);
|
void *read_hook_data);
|
||||||
|
|
||||||
static void
|
static grub_err_t
|
||||||
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
|
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
|
||||||
{
|
{
|
||||||
at->mft = mft;
|
at->mft = mft;
|
||||||
at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
|
at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
|
||||||
at->attr_nxt = mft->buf + first_attr_off (mft->buf);
|
at->attr_nxt = mft->buf + first_attr_off (mft->buf);
|
||||||
|
at->end = mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||||
|
|
||||||
|
if (at->attr_nxt > at->end)
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "attributes start outside the MFT");
|
||||||
|
|
||||||
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
|
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -139,16 +320,26 @@ free_attr (struct grub_ntfs_attr *at)
|
||||||
static grub_uint8_t *
|
static grub_uint8_t *
|
||||||
find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
{
|
{
|
||||||
|
grub_uint8_t *mft_end;
|
||||||
|
grub_uint16_t nsize;
|
||||||
|
grub_uint16_t nxt_offset;
|
||||||
|
grub_uint32_t edat_offset;
|
||||||
|
|
||||||
|
/* GRUB_NTFS_AF_ALST indicates the attribute list type */
|
||||||
if (at->flags & GRUB_NTFS_AF_ALST)
|
if (at->flags & GRUB_NTFS_AF_ALST)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
while (at->attr_nxt < at->attr_end)
|
while (at->attr_nxt)
|
||||||
{
|
{
|
||||||
at->attr_cur = at->attr_nxt;
|
at->attr_cur = at->attr_nxt;
|
||||||
at->attr_nxt += u16at (at->attr_cur, 4);
|
/*
|
||||||
|
* Go to the next attribute in the list but do not validate
|
||||||
|
* because this is the attribute list type.
|
||||||
|
*/
|
||||||
|
at->attr_nxt = next_attribute (at->attr_cur, at->attr_end, false);
|
||||||
if ((*at->attr_cur == attr) || (attr == 0))
|
if ((*at->attr_cur == attr) || (attr == 0))
|
||||||
{
|
{
|
||||||
grub_uint8_t *new_pos;
|
grub_uint8_t *new_pos, *end;
|
||||||
|
|
||||||
if (at->flags & GRUB_NTFS_AF_MMFT)
|
if (at->flags & GRUB_NTFS_AF_MMFT)
|
||||||
{
|
{
|
||||||
|
@ -172,15 +363,41 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only time emft_bufs is defined is in this function, with this
|
||||||
|
* size.
|
||||||
|
*/
|
||||||
|
grub_size_t emft_buf_size =
|
||||||
|
at->mft->data->mft_size << GRUB_NTFS_BLK_SHR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Needs to be enough space for the successful case to even
|
||||||
|
* bother.
|
||||||
|
*/
|
||||||
|
if (first_attr_off (at->emft_buf) >= (emft_buf_size - 0x18 - 2))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS,
|
||||||
|
"can\'t find 0x%X in attribute list",
|
||||||
|
(unsigned char) *at->attr_cur);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
|
new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
|
||||||
while (*new_pos != 0xFF)
|
end = &at->emft_buf[emft_buf_size];
|
||||||
|
at->end = end;
|
||||||
|
|
||||||
|
while (new_pos && *new_pos != 0xFF)
|
||||||
{
|
{
|
||||||
if ((*new_pos == *at->attr_cur)
|
if ((*new_pos == *at->attr_cur)
|
||||||
&& (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
|
&& (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
|
||||||
{
|
{
|
||||||
return new_pos;
|
return new_pos;
|
||||||
}
|
}
|
||||||
new_pos += u16at (new_pos, 4);
|
/*
|
||||||
|
* Go to the next attribute in the list but do not validate
|
||||||
|
* because this is the attribute list type.
|
||||||
|
*/
|
||||||
|
new_pos = next_attribute (new_pos, end, false);
|
||||||
}
|
}
|
||||||
grub_error (GRUB_ERR_BAD_FS,
|
grub_error (GRUB_ERR_BAD_FS,
|
||||||
"can\'t find 0x%X in attribute list",
|
"can\'t find 0x%X in attribute list",
|
||||||
|
@ -191,12 +408,27 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
at->attr_cur = at->attr_nxt;
|
at->attr_cur = at->attr_nxt;
|
||||||
while (*at->attr_cur != 0xFF)
|
mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||||
|
while (at->attr_cur >= at->mft->buf && at->attr_cur < (mft_end - 4)
|
||||||
|
&& *at->attr_cur != 0xFF)
|
||||||
{
|
{
|
||||||
at->attr_nxt += u16at (at->attr_cur, 4);
|
/*
|
||||||
|
* We can't use validate_attribute here because this logic
|
||||||
|
* seems to be used for both parsing through attributes
|
||||||
|
* and attribute lists.
|
||||||
|
*/
|
||||||
|
nsize = u16at (at->attr_cur, 4);
|
||||||
|
if (at->attr_cur + grub_max (GRUB_NTFS_ATTRIBUTE_HEADER_SIZE, nsize) >= at->end)
|
||||||
|
{
|
||||||
|
at->attr_nxt = at->attr_cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
at->attr_nxt = at->attr_cur + nsize;
|
||||||
|
|
||||||
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
|
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
|
||||||
at->attr_end = at->attr_cur;
|
at->attr_end = at->attr_cur;
|
||||||
if ((*at->attr_cur == attr) || (attr == 0))
|
if ((*at->attr_cur == attr) || (attr == 0) || (nsize == 0))
|
||||||
return at->attr_cur;
|
return at->attr_cur;
|
||||||
at->attr_cur = at->attr_nxt;
|
at->attr_cur = at->attr_nxt;
|
||||||
}
|
}
|
||||||
|
@ -226,23 +458,54 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
at->attr_nxt = at->edat_buf;
|
at->attr_nxt = at->edat_buf;
|
||||||
at->attr_end = at->edat_buf + u32at (pa, 0x30);
|
edat_offset = u32at (pa, 0x30);
|
||||||
|
if (edat_offset >= n)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
at->attr_end = at->edat_buf + edat_offset;
|
||||||
pa_end = at->edat_buf + n;
|
pa_end = at->edat_buf + n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
at->attr_nxt = at->attr_end + res_attr_data_off (pa);
|
at->attr_nxt = at->attr_end + res_attr_data_off (pa);
|
||||||
at->attr_end = at->attr_end + u32at (pa, 4);
|
edat_offset = u32at (pa, 4);
|
||||||
|
if ((at->attr_end + edat_offset) >= (at->end))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
at->attr_end = at->attr_end + edat_offset;
|
||||||
pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||||
}
|
}
|
||||||
at->flags |= GRUB_NTFS_AF_ALST;
|
at->flags |= GRUB_NTFS_AF_ALST;
|
||||||
while (at->attr_nxt < at->attr_end)
|
|
||||||
|
/* From this point on pa_end is the end of the buffer */
|
||||||
|
at->end = pa_end;
|
||||||
|
|
||||||
|
if (at->attr_end >= pa_end || at->attr_nxt >= pa_end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (at->attr_nxt)
|
||||||
{
|
{
|
||||||
if ((*at->attr_nxt == attr) || (attr == 0))
|
if ((*at->attr_nxt == attr) || (attr == 0))
|
||||||
break;
|
break;
|
||||||
at->attr_nxt += u16at (at->attr_nxt, 4);
|
|
||||||
|
nxt_offset = u16at (at->attr_nxt, 4);
|
||||||
|
at->attr_nxt += nxt_offset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop and set attr_nxt to NULL when either the next offset is zero,
|
||||||
|
* or when the pointer is within four bytes of the end of the buffer
|
||||||
|
* since we could attempt to access attr_nxt + 4 bytes offset above to
|
||||||
|
* get the next 16-bit 'nxt_offset' value.
|
||||||
|
*/
|
||||||
|
if (nxt_offset == 0 || at->attr_nxt >= (pa_end - 4))
|
||||||
|
at->attr_nxt = NULL;
|
||||||
}
|
}
|
||||||
if (at->attr_nxt >= at->attr_end)
|
|
||||||
|
if ((at->attr_nxt + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE) >= at->attr_end || at->attr_nxt == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
|
if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
|
||||||
|
@ -263,7 +526,11 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
grub_cpu_to_le32 (at->mft->data->mft_start
|
grub_cpu_to_le32 (at->mft->data->mft_start
|
||||||
+ 1));
|
+ 1));
|
||||||
pa = at->attr_nxt + u16at (pa, 4);
|
pa = at->attr_nxt + u16at (pa, 4);
|
||||||
while (pa < at->attr_end)
|
|
||||||
|
if (pa >= pa_end)
|
||||||
|
pa = NULL;
|
||||||
|
|
||||||
|
while (pa)
|
||||||
{
|
{
|
||||||
if (*pa != attr)
|
if (*pa != attr)
|
||||||
break;
|
break;
|
||||||
|
@ -280,6 +547,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||||
at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
|
at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
pa += u16at (pa, 4);
|
pa += u16at (pa, 4);
|
||||||
|
if (pa >= pa_end)
|
||||||
|
pa = NULL;
|
||||||
}
|
}
|
||||||
at->attr_nxt = at->attr_cur;
|
at->attr_nxt = at->attr_cur;
|
||||||
at->flags &= ~GRUB_NTFS_AF_GPOS;
|
at->flags &= ~GRUB_NTFS_AF_GPOS;
|
||||||
|
@ -294,24 +563,31 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
|
||||||
grub_uint8_t attr)
|
grub_uint8_t attr)
|
||||||
{
|
{
|
||||||
grub_uint8_t *pa;
|
grub_uint8_t *pa;
|
||||||
|
grub_uint8_t *last_pa;
|
||||||
|
|
||||||
|
if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
init_attr (at, mft);
|
|
||||||
pa = find_attr (at, attr);
|
pa = find_attr (at, attr);
|
||||||
if (pa == NULL)
|
if (pa == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((at->flags & GRUB_NTFS_AF_ALST) == 0)
|
if ((at->flags & GRUB_NTFS_AF_ALST) == 0)
|
||||||
{
|
{
|
||||||
|
/* Used to make sure we're not stuck in a loop. */
|
||||||
|
last_pa = NULL;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
pa = find_attr (at, attr);
|
pa = find_attr (at, attr);
|
||||||
if (pa == NULL)
|
if (pa == NULL || pa == last_pa)
|
||||||
break;
|
break;
|
||||||
if (at->flags & GRUB_NTFS_AF_ALST)
|
if (at->flags & GRUB_NTFS_AF_ALST)
|
||||||
return pa;
|
return pa;
|
||||||
|
last_pa = pa;
|
||||||
}
|
}
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
free_attr (at);
|
free_attr (at);
|
||||||
init_attr (at, mft);
|
if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||||
|
return NULL;
|
||||||
pa = find_attr (at, attr);
|
pa = find_attr (at, attr);
|
||||||
}
|
}
|
||||||
return pa;
|
return pa;
|
||||||
|
@ -363,7 +639,7 @@ retry:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "run list overflown");
|
return grub_error (GRUB_ERR_BAD_FS, "run list overflow");
|
||||||
}
|
}
|
||||||
ctx->curr_vcn = ctx->next_vcn;
|
ctx->curr_vcn = ctx->next_vcn;
|
||||||
ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */
|
ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */
|
||||||
|
@ -402,6 +678,8 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
|
||||||
grub_disk_read_hook_t read_hook, void *read_hook_data)
|
grub_disk_read_hook_t read_hook, void *read_hook_data)
|
||||||
{
|
{
|
||||||
struct grub_ntfs_rlst cc, *ctx;
|
struct grub_ntfs_rlst cc, *ctx;
|
||||||
|
grub_uint8_t *end_ptr = (pa + len);
|
||||||
|
grub_uint16_t run_offset;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -434,7 +712,11 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->cur_run = pa + u16at (pa, 0x20);
|
run_offset = u16at (pa, 0x20);
|
||||||
|
if ((run_offset + pa) >= end_ptr || ((run_offset + pa) >= (at->end)))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "run offset out of range");
|
||||||
|
|
||||||
|
ctx->cur_run = pa + run_offset;
|
||||||
|
|
||||||
ctx->next_vcn = u32at (pa, 0x10);
|
ctx->next_vcn = u32at (pa, 0x10);
|
||||||
ctx->curr_lcn = 0;
|
ctx->curr_lcn = 0;
|
||||||
|
@ -497,6 +779,8 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||||
grub_uint8_t *pp;
|
grub_uint8_t *pp;
|
||||||
grub_err_t ret;
|
grub_err_t ret;
|
||||||
|
|
||||||
|
if (at == NULL || at->attr_cur == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "attribute not found");
|
||||||
save_cur = at->attr_cur;
|
save_cur = at->attr_cur;
|
||||||
at->attr_nxt = at->attr_cur;
|
at->attr_nxt = at->attr_cur;
|
||||||
attr = *at->attr_nxt;
|
attr = *at->attr_nxt;
|
||||||
|
@ -513,14 +797,17 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||||
else
|
else
|
||||||
vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
|
vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
|
||||||
pa = at->attr_nxt + u16at (at->attr_nxt, 4);
|
pa = at->attr_nxt + u16at (at->attr_nxt, 4);
|
||||||
while (pa < at->attr_end)
|
if (validate_attribute (pa, at->attr_end) == false)
|
||||||
|
pa = NULL;
|
||||||
|
|
||||||
|
while (pa)
|
||||||
{
|
{
|
||||||
if (*pa != attr)
|
if (*pa != attr)
|
||||||
break;
|
break;
|
||||||
if (u32at (pa, 8) > vcn)
|
if (u32at (pa, 8) > vcn)
|
||||||
break;
|
break;
|
||||||
at->attr_nxt = pa;
|
at->attr_nxt = pa;
|
||||||
pa += u16at (pa, 4);
|
pa = next_attribute (pa, at->attr_end, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pp = find_attr (at, attr);
|
pp = find_attr (at, attr);
|
||||||
|
@ -582,7 +869,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
|
||||||
mft->attr.attr_end = 0; /* Don't jump to attribute list */
|
mft->attr.attr_end = 0; /* Don't jump to attribute list */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
init_attr (&mft->attr, mft);
|
return init_attr (&mft->attr, mft);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -590,8 +877,11 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
|
||||||
static void
|
static void
|
||||||
free_file (struct grub_ntfs_file *mft)
|
free_file (struct grub_ntfs_file *mft)
|
||||||
{
|
{
|
||||||
|
if (mft)
|
||||||
|
{
|
||||||
free_attr (&mft->attr);
|
free_attr (&mft->attr);
|
||||||
grub_free (mft->buf);
|
grub_free (mft->buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -622,6 +912,7 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos
|
||||||
{
|
{
|
||||||
grub_uint8_t *np;
|
grub_uint8_t *np;
|
||||||
int ns;
|
int ns;
|
||||||
|
grub_uint16_t pos_incr;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -684,7 +975,12 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos
|
||||||
|
|
||||||
grub_free (ustr);
|
grub_free (ustr);
|
||||||
}
|
}
|
||||||
pos += u16at (pos, 8);
|
pos_incr = u16at (pos, 8);
|
||||||
|
if (pos_incr > 0)
|
||||||
|
pos += pos_incr;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -795,6 +1091,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
grub_size_t bitmap_len;
|
grub_size_t bitmap_len;
|
||||||
struct grub_ntfs_file *mft;
|
struct grub_ntfs_file *mft;
|
||||||
|
/* Used to make sure we're not stuck in a loop. */
|
||||||
|
grub_uint8_t *last_pos = NULL;
|
||||||
|
grub_uint32_t tmp_len;
|
||||||
|
|
||||||
mft = (struct grub_ntfs_file *) dir;
|
mft = (struct grub_ntfs_file *) dir;
|
||||||
|
|
||||||
|
@ -808,15 +1107,18 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
bmp = NULL;
|
bmp = NULL;
|
||||||
|
|
||||||
at = &attr;
|
at = &attr;
|
||||||
init_attr (at, mft);
|
if (init_attr (at, mft) != GRUB_ERR_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
|
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
|
||||||
if (cur_pos == NULL)
|
if (cur_pos == NULL || cur_pos == last_pos)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
|
grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
last_pos = cur_pos;
|
||||||
|
|
||||||
/* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
|
/* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
|
||||||
if ((u32at (cur_pos, 8) != 0x180400) ||
|
if ((u32at (cur_pos, 8) != 0x180400) ||
|
||||||
|
@ -824,6 +1126,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
(u32at (cur_pos, 0x1C) != 0x300033))
|
(u32at (cur_pos, 0x1C) != 0x300033))
|
||||||
continue;
|
continue;
|
||||||
cur_pos += res_attr_data_off (cur_pos);
|
cur_pos += res_attr_data_off (cur_pos);
|
||||||
|
if(cur_pos >= at->end)
|
||||||
|
continue;
|
||||||
if (*cur_pos != 0x30) /* Not filename index */
|
if (*cur_pos != 0x30) /* Not filename index */
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
@ -839,11 +1143,21 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
bitmap = NULL;
|
bitmap = NULL;
|
||||||
bitmap_len = 0;
|
bitmap_len = 0;
|
||||||
free_attr (at);
|
free_attr (at);
|
||||||
|
/* No need to check errors here, as it will already be fine */
|
||||||
init_attr (at, mft);
|
init_attr (at, mft);
|
||||||
|
|
||||||
|
last_pos = NULL;
|
||||||
while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
|
while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
|
||||||
{
|
{
|
||||||
int ofs;
|
int ofs;
|
||||||
|
|
||||||
|
if (cur_pos == last_pos)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "bitmap attribute loop");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
last_pos = cur_pos;
|
||||||
|
|
||||||
ofs = cur_pos[0xA];
|
ofs = cur_pos[0xA];
|
||||||
/* Namelen=4, Name="$I30" */
|
/* Namelen=4, Name="$I30" */
|
||||||
if ((cur_pos[9] == 4) &&
|
if ((cur_pos[9] == 4) &&
|
||||||
|
@ -891,7 +1205,15 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
"fails to read non-resident $BITMAP");
|
"fails to read non-resident $BITMAP");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
bitmap_len = u32at (cur_pos, 0x30);
|
tmp_len = u32at (cur_pos, 0x30);
|
||||||
|
if (tmp_len <= bitmap_len)
|
||||||
|
bitmap_len = tmp_len;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS,
|
||||||
|
"bitmap len too large for non-resident $BITMAP");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap = bmp;
|
bitmap = bmp;
|
||||||
|
@ -900,6 +1222,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
free_attr (at);
|
free_attr (at);
|
||||||
|
last_pos = NULL;
|
||||||
cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION);
|
cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION);
|
||||||
while (cur_pos != NULL)
|
while (cur_pos != NULL)
|
||||||
{
|
{
|
||||||
|
@ -909,6 +1232,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
(u32at (cur_pos, 0x44) == 0x300033))
|
(u32at (cur_pos, 0x44) == 0x300033))
|
||||||
break;
|
break;
|
||||||
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION);
|
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION);
|
||||||
|
if (cur_pos == last_pos)
|
||||||
|
break;
|
||||||
|
last_pos = cur_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!cur_pos) && (bitmap))
|
if ((!cur_pos) && (bitmap))
|
||||||
|
@ -1204,6 +1530,7 @@ grub_ntfs_label (grub_device_t device, char **label)
|
||||||
struct grub_ntfs_data *data = 0;
|
struct grub_ntfs_data *data = 0;
|
||||||
struct grub_fshelp_node *mft = 0;
|
struct grub_fshelp_node *mft = 0;
|
||||||
grub_uint8_t *pa;
|
grub_uint8_t *pa;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
grub_dl_ref (my_mod);
|
||||||
|
|
||||||
|
@ -1229,10 +1556,13 @@ grub_ntfs_label (grub_device_t device, char **label)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_attr (&mft->attr, mft);
|
err = init_attr (&mft->attr, mft);
|
||||||
|
if (err != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
|
||||||
pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
|
pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
|
||||||
|
|
||||||
if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
|
if (pa == NULL || pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
|
grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1250,7 +1580,8 @@ grub_ntfs_label (grub_device_t device, char **label)
|
||||||
|
|
||||||
len = res_attr_data_len (pa) / 2;
|
len = res_attr_data_len (pa) / 2;
|
||||||
pa += res_attr_data_off (pa);
|
pa += res_attr_data_off (pa);
|
||||||
if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
|
if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len &&
|
||||||
|
pa >= mft->buf && (pa + len < (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))))
|
||||||
*label = get_utf8 (pa, len);
|
*label = get_utf8 (pa, len);
|
||||||
else
|
else
|
||||||
grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
|
grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
|
||||||
|
@ -1320,11 +1651,16 @@ static struct grub_fs grub_ntfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT (ntfs)
|
GRUB_MOD_INIT (ntfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_ntfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_ntfs_fs);
|
grub_fs_register (&grub_ntfs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (ntfs)
|
GRUB_MOD_FINI (ntfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_ntfs_fs);
|
grub_fs_unregister (&grub_ntfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/ntfs.h>
|
#include <grub/ntfs.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ static grub_err_t
|
||||||
decomp_nextvcn (struct grub_ntfs_comp *cc)
|
decomp_nextvcn (struct grub_ntfs_comp *cc)
|
||||||
{
|
{
|
||||||
if (cc->comp_head >= cc->comp_tail)
|
if (cc->comp_head >= cc->comp_tail)
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "compression block overflown");
|
return grub_error (GRUB_ERR_BAD_FS, "compression block overflow");
|
||||||
if (grub_disk_read
|
if (grub_disk_read
|
||||||
(cc->disk,
|
(cc->disk,
|
||||||
(cc->comp_table[cc->comp_head].next_lcn -
|
(cc->comp_table[cc->comp_head].next_lcn -
|
||||||
|
@ -310,6 +311,7 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||||
{
|
{
|
||||||
grub_err_t ret;
|
grub_err_t ret;
|
||||||
grub_disk_addr_t vcn;
|
grub_disk_addr_t vcn;
|
||||||
|
int log_sz;
|
||||||
|
|
||||||
if (ctx->attr->sbuf)
|
if (ctx->attr->sbuf)
|
||||||
{
|
{
|
||||||
|
@ -349,7 +351,12 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->comp.comp_head = ctx->comp.comp_tail = 0;
|
ctx->comp.comp_head = ctx->comp.comp_tail = 0;
|
||||||
ctx->comp.cbuf = grub_malloc (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR));
|
if (grub_add (ctx->comp.log_spc, GRUB_NTFS_BLK_SHR, &log_sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("compression buffer size overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx->comp.cbuf = grub_malloc (1 << log_sz);
|
||||||
if (!ctx->comp.cbuf)
|
if (!ctx->comp.cbuf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ read_number (const char *str, grub_size_t size)
|
||||||
|
|
||||||
GRUB_MOD_INIT (odc)
|
GRUB_MOD_INIT (odc)
|
||||||
{
|
{
|
||||||
|
grub_cpio_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cpio_fs);
|
grub_fs_register (&grub_cpio_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,6 +192,7 @@ static struct grub_fs grub_procfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT (procfs)
|
GRUB_MOD_INIT (procfs)
|
||||||
{
|
{
|
||||||
|
grub_procfs_fs.mod = mod;
|
||||||
grub_disk_dev_register (&grub_procfs_dev);
|
grub_disk_dev_register (&grub_procfs_dev);
|
||||||
grub_fs_register (&grub_procfs_fs);
|
grub_fs_register (&grub_procfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -1417,11 +1418,16 @@ static struct grub_fs grub_reiserfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(reiserfs)
|
GRUB_MOD_INIT(reiserfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_reiserfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_reiserfs_fs);
|
grub_fs_register (&grub_reiserfs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(reiserfs)
|
GRUB_MOD_FINI(reiserfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_reiserfs_fs);
|
grub_fs_unregister (&grub_reiserfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
#include <grub/fs.h>
|
#include <grub/fs.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -475,10 +476,15 @@ static struct grub_fs grub_romfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(romfs)
|
GRUB_MOD_INIT(romfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_romfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_romfs_fs);
|
grub_fs_register (&grub_romfs_fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(romfs)
|
GRUB_MOD_FINI(romfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_romfs_fs);
|
grub_fs_unregister (&grub_romfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
#include <grub/safemath.h>
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
@ -428,6 +429,9 @@ grub_sfs_mount (grub_disk_t disk)
|
||||||
- 24 /* offsetof (struct grub_sfs_objc, objects) */
|
- 24 /* offsetof (struct grub_sfs_objc, objects) */
|
||||||
- 25); /* offsetof (struct grub_sfs_obj, filename) */
|
- 25); /* offsetof (struct grub_sfs_obj, filename) */
|
||||||
data->label = grub_zalloc (max_len + 1);
|
data->label = grub_zalloc (max_len + 1);
|
||||||
|
if (data->label == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
grub_strncpy (data->label, (char *) rootobjc->objects[0].filename, max_len);
|
grub_strncpy (data->label, (char *) rootobjc->objects[0].filename, max_len);
|
||||||
|
|
||||||
grub_free (rootobjc_data);
|
grub_free (rootobjc_data);
|
||||||
|
@ -779,11 +783,16 @@ static struct grub_fs grub_sfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(sfs)
|
GRUB_MOD_INIT(sfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_sfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_sfs_fs);
|
grub_fs_register (&grub_sfs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(sfs)
|
GRUB_MOD_FINI(sfs)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_sfs_fs);
|
grub_fs_unregister (&grub_sfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -460,11 +460,11 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_size_t sz;
|
grub_uint32_t sz;
|
||||||
|
|
||||||
if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
|
if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink name length overflow"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +580,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||||
struct grub_squash_dirent di;
|
struct grub_squash_dirent di;
|
||||||
struct grub_squash_inode ino;
|
struct grub_squash_inode ino;
|
||||||
grub_size_t sz;
|
grub_size_t sz;
|
||||||
|
grub_uint16_t nlen;
|
||||||
|
|
||||||
err = read_chunk (dir->data, &di, sizeof (di),
|
err = read_chunk (dir->data, &di, sizeof (di),
|
||||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||||
|
@ -595,7 +596,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||||
if (err)
|
if (err)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2);
|
if (grub_add (grub_le_to_cpu16 (di.namelen), 2, &nlen))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buf = grub_malloc (nlen);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
err = read_chunk (dir->data, buf,
|
err = read_chunk (dir->data, buf,
|
||||||
|
@ -816,10 +822,10 @@ direct_read (struct grub_squash_data *data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz);
|
total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz);
|
||||||
ino->block_sizes = grub_malloc (total_blocks
|
ino->block_sizes = grub_calloc (total_blocks,
|
||||||
* sizeof (ino->block_sizes[0]));
|
sizeof (ino->block_sizes[0]));
|
||||||
ino->cumulated_block_sizes = grub_malloc (total_blocks
|
ino->cumulated_block_sizes = grub_calloc (total_blocks,
|
||||||
* sizeof (ino->cumulated_block_sizes[0]));
|
sizeof (ino->cumulated_block_sizes[0]));
|
||||||
if (!ino->block_sizes || !ino->cumulated_block_sizes)
|
if (!ino->block_sizes || !ino->cumulated_block_sizes)
|
||||||
{
|
{
|
||||||
grub_free (ino->block_sizes);
|
grub_free (ino->block_sizes);
|
||||||
|
@ -1044,6 +1050,7 @@ static struct grub_fs grub_squash_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(squash4)
|
GRUB_MOD_INIT(squash4)
|
||||||
{
|
{
|
||||||
|
grub_squash_fs.mod = mod;
|
||||||
grub_fs_register (&grub_squash_fs);
|
grub_fs_register (&grub_squash_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -76,8 +77,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
{
|
{
|
||||||
struct head hd;
|
struct head hd;
|
||||||
int reread = 0, have_longname = 0, have_longlink = 0;
|
int reread = 0, have_longname = 0, have_longlink = 0;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
data->hofs = data->next_hofs;
|
data->hofs = data->next_hofs;
|
||||||
|
*name = NULL;
|
||||||
|
|
||||||
for (reread = 0; reread < 3; reread++)
|
for (reread = 0; reread < 3; reread++)
|
||||||
{
|
{
|
||||||
|
@ -96,8 +99,13 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
if (hd.typeflag == 'L')
|
if (hd.typeflag == 'L')
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
|
grub_size_t namesize;
|
||||||
*name = grub_malloc (namesize + 1);
|
|
||||||
|
if (grub_cast (read_number (hd.size, sizeof (hd.size)), &namesize) ||
|
||||||
|
grub_add (namesize, 1, &sz))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow"));
|
||||||
|
|
||||||
|
*name = grub_malloc (sz);
|
||||||
if (*name == NULL)
|
if (*name == NULL)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
err = grub_disk_read (data->disk, 0,
|
err = grub_disk_read (data->disk, 0,
|
||||||
|
@ -116,16 +124,21 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
if (hd.typeflag == 'K')
|
if (hd.typeflag == 'K')
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
|
grub_size_t linksize;
|
||||||
if (data->linkname_alloc < linksize + 1)
|
|
||||||
|
if (grub_cast (read_number (hd.size, sizeof (hd.size)), &linksize) ||
|
||||||
|
grub_add (linksize, 1, &sz))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow"));
|
||||||
|
|
||||||
|
if (data->linkname_alloc < sz)
|
||||||
{
|
{
|
||||||
char *n;
|
char *n;
|
||||||
n = grub_calloc (2, linksize + 1);
|
n = grub_calloc (2, sz);
|
||||||
if (!n)
|
if (!n)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
grub_free (data->linkname);
|
grub_free (data->linkname);
|
||||||
data->linkname = n;
|
data->linkname = n;
|
||||||
data->linkname_alloc = 2 * (linksize + 1);
|
data->linkname_alloc = 2 * (sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = grub_disk_read (data->disk, 0,
|
err = grub_disk_read (data->disk, 0,
|
||||||
|
@ -148,7 +161,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
while (extra_size < sizeof (hd.prefix)
|
while (extra_size < sizeof (hd.prefix)
|
||||||
&& hd.prefix[extra_size])
|
&& hd.prefix[extra_size])
|
||||||
extra_size++;
|
extra_size++;
|
||||||
*name = grub_malloc (sizeof (hd.name) + extra_size + 2);
|
|
||||||
|
if (grub_add (sizeof (hd.name) + 2, extra_size, &sz))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("long name size overflow"));
|
||||||
|
*name = grub_malloc (sz);
|
||||||
if (*name == NULL)
|
if (*name == NULL)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
if (hd.prefix[0])
|
if (hd.prefix[0])
|
||||||
|
@ -160,15 +176,22 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
(*name)[extra_size + sizeof (hd.name)] = 0;
|
(*name)[extra_size + sizeof (hd.name)] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->size = read_number (hd.size, sizeof (hd.size));
|
if (grub_cast (read_number (hd.size, sizeof (hd.size)), &data->size))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow"));
|
||||||
|
|
||||||
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
||||||
data->next_hofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
data->next_hofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||||
~(GRUB_DISK_SECTOR_SIZE - 1));
|
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||||
if (mtime)
|
if (mtime)
|
||||||
*mtime = read_number (hd.mtime, sizeof (hd.mtime));
|
{
|
||||||
|
if (grub_cast (read_number (hd.mtime, sizeof (hd.mtime)), mtime))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow"));
|
||||||
|
}
|
||||||
if (mode)
|
if (mode)
|
||||||
{
|
{
|
||||||
*mode = read_number (hd.mode, sizeof (hd.mode));
|
if (grub_cast (read_number (hd.mode, sizeof (hd.mode)), mode))
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow"));
|
||||||
|
|
||||||
switch (hd.typeflag)
|
switch (hd.typeflag)
|
||||||
{
|
{
|
||||||
/* Hardlink. */
|
/* Hardlink. */
|
||||||
|
@ -202,6 +225,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||||
}
|
}
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*name == NULL)
|
||||||
|
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +363,7 @@ static struct grub_fs grub_cpio_fs = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (tar)
|
GRUB_MOD_INIT (tar)
|
||||||
{
|
{
|
||||||
|
grub_cpio_fs.mod = mod;
|
||||||
grub_fs_register (&grub_cpio_fs);
|
grub_fs_register (&grub_cpio_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
#include <grub/charset.h>
|
#include <grub/charset.h>
|
||||||
#include <grub/datetime.h>
|
#include <grub/datetime.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
#include <grub/udf.h>
|
#include <grub/udf.h>
|
||||||
#include <grub/safemath.h>
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
|
@ -1455,11 +1456,16 @@ static struct grub_fs grub_udf_fs = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (udf)
|
GRUB_MOD_INIT (udf)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_udf_fs.mod = mod;
|
||||||
grub_fs_register (&grub_udf_fs);
|
grub_fs_register (&grub_udf_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (udf)
|
GRUB_MOD_FINI (udf)
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_udf_fs);
|
grub_fs_unregister (&grub_udf_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -463,7 +464,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||||
/* Check against zero is paylindromic, no need to swap. */
|
/* Check against zero is paylindromic, no need to swap. */
|
||||||
if (data->inode.nblocks == 0
|
if (data->inode.nblocks == 0
|
||||||
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
||||||
grub_strcpy (symlink, (char *) data->inode.symlink);
|
grub_strlcpy (symlink, (char *) data->inode.symlink, sz);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
|
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
|
||||||
|
@ -899,7 +900,11 @@ GRUB_MOD_INIT(ufs1)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
|
{
|
||||||
|
grub_ufs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_ufs_fs);
|
grub_fs_register (&grub_ufs_fs);
|
||||||
|
}
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,6 +918,7 @@ GRUB_MOD_FINI(ufs1)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
if (!grub_is_lockdown ())
|
||||||
grub_fs_unregister (&grub_ufs_fs);
|
grub_fs_unregister (&grub_ufs_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
|
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
|
||||||
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
|
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
|
||||||
#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
|
#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_EXCHRANGE (1 << 6) /* exchangerange supported */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 7) /* parent pointers */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 8) /* metadata dir tree */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory entries with ftype are explicitly handled by GRUB code.
|
* Directory entries with ftype are explicitly handled by GRUB code.
|
||||||
|
@ -98,6 +101,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
*
|
*
|
||||||
* We do not currently verify metadata UUID, so it is safe to read filesystems
|
* We do not currently verify metadata UUID, so it is safe to read filesystems
|
||||||
* with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
|
* with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
|
||||||
|
*
|
||||||
|
* We do not currently replay the log, so it is safe to read filesystems
|
||||||
|
* with the XFS_SB_FEAT_INCOMPAT_EXCHRANGE feature.
|
||||||
|
*
|
||||||
|
* We do not currently read directory parent pointers, so it is safe to read
|
||||||
|
* filesystems with the XFS_SB_FEAT_INCOMPAT_PARENT feature.
|
||||||
|
*
|
||||||
|
* We do not currently look at realtime or quota metadata, so it is safe to
|
||||||
|
* read filesystems with the XFS_SB_FEAT_INCOMPAT_METADIR feature.
|
||||||
*/
|
*/
|
||||||
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
|
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
|
||||||
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
|
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
|
||||||
|
@ -105,7 +117,10 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
XFS_SB_FEAT_INCOMPAT_META_UUID | \
|
XFS_SB_FEAT_INCOMPAT_META_UUID | \
|
||||||
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
|
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
|
||||||
XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
|
XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
|
||||||
XFS_SB_FEAT_INCOMPAT_NREXT64)
|
XFS_SB_FEAT_INCOMPAT_NREXT64 | \
|
||||||
|
XFS_SB_FEAT_INCOMPAT_EXCHRANGE | \
|
||||||
|
XFS_SB_FEAT_INCOMPAT_PARENT | \
|
||||||
|
XFS_SB_FEAT_INCOMPAT_METADIR)
|
||||||
|
|
||||||
struct grub_xfs_sblock
|
struct grub_xfs_sblock
|
||||||
{
|
{
|
||||||
|
@ -327,6 +342,8 @@ static int grub_xfs_sb_valid(struct grub_xfs_data *data)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "unsupported XFS filesystem version");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,6 +612,17 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
grub_uint64_t i;
|
grub_uint64_t i;
|
||||||
|
grub_addr_t keys_end, data_end;
|
||||||
|
|
||||||
|
if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) ||
|
||||||
|
grub_add ((grub_addr_t) keys, keys_end, &keys_end) ||
|
||||||
|
grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) ||
|
||||||
|
keys_end > data_end)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS root keys");
|
||||||
|
grub_free (leaf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < nrec; i++)
|
for (i = 0; i < nrec; i++)
|
||||||
{
|
{
|
||||||
|
@ -705,6 +733,7 @@ static char *
|
||||||
grub_xfs_read_symlink (grub_fshelp_node_t node)
|
grub_xfs_read_symlink (grub_fshelp_node_t node)
|
||||||
{
|
{
|
||||||
grub_ssize_t size = grub_be_to_cpu64 (node->inode.size);
|
grub_ssize_t size = grub_be_to_cpu64 (node->inode.size);
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
|
@ -726,7 +755,12 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
|
||||||
if (node->data->hascrc)
|
if (node->data->hascrc)
|
||||||
off = 56;
|
off = 56;
|
||||||
|
|
||||||
symlink = grub_malloc (size + 1);
|
if (grub_add (size, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
symlink = grub_malloc (sz);
|
||||||
if (!symlink)
|
if (!symlink)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -776,8 +810,15 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
|
||||||
{
|
{
|
||||||
struct grub_fshelp_node *fdiro;
|
struct grub_fshelp_node *fdiro;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1);
|
if (grub_add (grub_xfs_fshelp_size(ctx->diro->data), 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory data size overflow"));
|
||||||
|
grub_print_error ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fdiro = grub_malloc (sz);
|
||||||
if (!fdiro)
|
if (!fdiro)
|
||||||
{
|
{
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
|
@ -844,7 +885,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
grub_uint8_t c;
|
grub_uint8_t c;
|
||||||
|
|
||||||
if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
|
if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode");
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "invalid XFS inode");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* inopos might be unaligned. */
|
/* inopos might be unaligned. */
|
||||||
if (smallino)
|
if (smallino)
|
||||||
|
@ -902,6 +947,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
grub_xfs_first_de(dir->data, dirblock);
|
grub_xfs_first_de(dir->data, dirblock);
|
||||||
int entries = -1;
|
int entries = -1;
|
||||||
char *end = dirblock + dirblk_size;
|
char *end = dirblock + dirblk_size;
|
||||||
|
grub_uint32_t magic;
|
||||||
|
|
||||||
numread = grub_xfs_read_file (dir, 0, 0,
|
numread = grub_xfs_read_file (dir, 0, 0,
|
||||||
blk << dirblk_log2,
|
blk << dirblk_log2,
|
||||||
|
@ -912,11 +958,20 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this data block isn't actually part of the extent list then
|
||||||
|
* grub_xfs_read_file() returns a block of zeros. So, if the magic
|
||||||
|
* number field is all zeros then this block should be skipped.
|
||||||
|
*/
|
||||||
|
magic = *(grub_uint32_t *)(void *) dirblock;
|
||||||
|
if (!magic)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leaf and tail information are only in the data block if the number
|
* Leaf and tail information are only in the data block if the number
|
||||||
* of extents is 1.
|
* of extents is 1.
|
||||||
*/
|
*/
|
||||||
if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
if (grub_xfs_get_inode_nextents (&dir->inode) == 1)
|
||||||
{
|
{
|
||||||
struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
|
struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
|
||||||
|
|
||||||
|
@ -953,7 +1008,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
|
||||||
filename = (char *)(direntry + 1);
|
filename = (char *)(direntry + 1);
|
||||||
if (filename + direntry->len + 1 > (char *) end)
|
if (filename + direntry->len + 1 > (char *) end)
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* The byte after the filename is for the filetype, padding, or
|
/* The byte after the filename is for the filetype, padding, or
|
||||||
tag, which is not used by GRUB. So it can be overwritten. */
|
tag, which is not used by GRUB. So it can be overwritten. */
|
||||||
|
@ -970,7 +1028,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
* The expected number of directory entries is only tracked for the
|
* The expected number of directory entries is only tracked for the
|
||||||
* single extent case.
|
* single extent case.
|
||||||
*/
|
*/
|
||||||
if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
|
if (grub_xfs_get_inode_nextents (&dir->inode) == 1)
|
||||||
{
|
{
|
||||||
/* Check if last direntry in this block is reached. */
|
/* Check if last direntry in this block is reached. */
|
||||||
entries--;
|
entries--;
|
||||||
|
@ -1047,7 +1105,7 @@ grub_xfs_mount (grub_disk_t disk)
|
||||||
return data;
|
return data;
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
|
||||||
grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem");
|
grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem");
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
@ -1281,6 +1339,7 @@ static struct grub_fs grub_xfs_fs =
|
||||||
|
|
||||||
GRUB_MOD_INIT(xfs)
|
GRUB_MOD_INIT(xfs)
|
||||||
{
|
{
|
||||||
|
grub_xfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_xfs_fs);
|
grub_fs_register (&grub_xfs_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,8 @@
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/safemath.h>
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
|
#include <zstd.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
#define ZPOOL_PROP_BOOTFS "bootfs"
|
#define ZPOOL_PROP_BOOTFS "bootfs"
|
||||||
|
@ -291,6 +293,9 @@ static const char *spa_feature_names[] = {
|
||||||
"com.delphix:embedded_data",
|
"com.delphix:embedded_data",
|
||||||
"com.delphix:extensible_dataset",
|
"com.delphix:extensible_dataset",
|
||||||
"org.open-zfs:large_blocks",
|
"org.open-zfs:large_blocks",
|
||||||
|
"com.klarasystems:vdev_zaps_v2",
|
||||||
|
"com.delphix:head_errlog",
|
||||||
|
"org.freebsd:zstd_compress",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -312,6 +317,40 @@ zlib_decompress (void *s, void *d,
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
zstd_decompress (void *ibuf, void *obuf, grub_size_t isize,
|
||||||
|
grub_size_t osize)
|
||||||
|
{
|
||||||
|
grub_size_t zstd_ret;
|
||||||
|
grub_uint32_t c_len;
|
||||||
|
grub_uint8_t *byte_buf = (grub_uint8_t *) ibuf;
|
||||||
|
|
||||||
|
if (isize < 8)
|
||||||
|
return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data too short");
|
||||||
|
|
||||||
|
c_len = grub_be_to_cpu32 (grub_get_unaligned32 (byte_buf));
|
||||||
|
|
||||||
|
if (c_len > isize - 8)
|
||||||
|
return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||||
|
"zstd data announced size overflow");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ZFS uses non-stadard magic for zstd streams. Rather than adjusting
|
||||||
|
* library functions, replace non-standard magic with standard one.
|
||||||
|
*/
|
||||||
|
byte_buf[4] = 0x28;
|
||||||
|
byte_buf[5] = 0xb5;
|
||||||
|
byte_buf[6] = 0x2f;
|
||||||
|
byte_buf[7] = 0xfd;
|
||||||
|
zstd_ret = ZSTD_decompress (obuf, osize, byte_buf + 4, c_len + 4);
|
||||||
|
|
||||||
|
if (ZSTD_isError (zstd_ret))
|
||||||
|
return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||||
|
"zstd data corrupted (error %d)", (int) zstd_ret);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
zle_decompress (void *s, void *d,
|
zle_decompress (void *s, void *d,
|
||||||
grub_size_t slen, grub_size_t dlen)
|
grub_size_t slen, grub_size_t dlen)
|
||||||
|
@ -362,6 +401,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
|
||||||
{"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */
|
{"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */
|
||||||
{"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */
|
{"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */
|
||||||
{"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */
|
{"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */
|
||||||
|
{"zstd", zstd_decompress}, /* ZIO_COMPRESS_ZSTD */
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
|
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
|
||||||
|
@ -614,6 +654,8 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist)
|
||||||
return grub_error (GRUB_ERR_BUG, "member drive unknown");
|
return grub_error (GRUB_ERR_BUG, "member drive unknown");
|
||||||
|
|
||||||
*nvlist = grub_malloc (VDEV_PHYS_SIZE);
|
*nvlist = grub_malloc (VDEV_PHYS_SIZE);
|
||||||
|
if (!*nvlist)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
/* Read in the vdev name-value pair list (112K). */
|
/* Read in the vdev name-value pair list (112K). */
|
||||||
err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0,
|
err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0,
|
||||||
|
@ -723,8 +765,13 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||||
{
|
{
|
||||||
fill->n_children = nelm;
|
fill->n_children = nelm;
|
||||||
|
|
||||||
fill->children = grub_zalloc (fill->n_children
|
fill->children = grub_calloc (fill->n_children,
|
||||||
* sizeof (fill->children[0]));
|
sizeof (fill->children[0]));
|
||||||
|
if (!fill->children)
|
||||||
|
{
|
||||||
|
grub_free (type);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nelm; i++)
|
for (i = 0; i < nelm; i++)
|
||||||
|
@ -1010,8 +1057,10 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0);
|
ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0);
|
||||||
err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian,
|
err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian,
|
||||||
nvlist, VDEV_PHYS_SIZE);
|
nvlist, VDEV_PHYS_SIZE);
|
||||||
if (err)
|
if (err) {
|
||||||
|
grub_free (nvlist);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
grub_dprintf ("zfs", "check 2 passed\n");
|
grub_dprintf ("zfs", "check 2 passed\n");
|
||||||
|
|
||||||
|
@ -1097,8 +1146,10 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
if (original)
|
if (original)
|
||||||
data->guid = poolguid;
|
data->guid = poolguid;
|
||||||
|
|
||||||
if (data->guid != poolguid)
|
if (data->guid != poolguid) {
|
||||||
|
grub_free (nvlist);
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "another zpool");
|
return grub_error (GRUB_ERR_BAD_FS, "another zpool");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char *nv;
|
char *nv;
|
||||||
|
@ -1139,9 +1190,12 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
{
|
{
|
||||||
grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
|
grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
|
||||||
err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
|
err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
|
||||||
|
grub_free(features);
|
||||||
|
grub_free(nvlist);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
grub_free(features);
|
||||||
}
|
}
|
||||||
grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
|
grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
|
||||||
grub_free (nvlist);
|
grub_free (nvlist);
|
||||||
|
@ -2387,6 +2441,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
zap_dnode->endian) << DNODE_SHIFT);
|
zap_dnode->endian) << DNODE_SHIFT);
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_zfs_endian_t endian;
|
grub_zfs_endian_t endian;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
if (zap_verify (zap, zap_dnode->endian))
|
if (zap_verify (zap, zap_dnode->endian))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2448,8 +2503,19 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
if (le->le_type != ZAP_CHUNK_ENTRY)
|
if (le->le_type != ZAP_CHUNK_ENTRY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
|
if (grub_mul (grub_zfs_to_cpu16 (le->le_name_length, endian), name_elem_length, &sz) ||
|
||||||
* name_elem_length + 1);
|
grub_add (sz, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow"));
|
||||||
|
grub_free (l);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
buf = grub_malloc (sz);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
grub_free (l);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
if (zap_leaf_array_get (l, endian, blksft,
|
if (zap_leaf_array_get (l, endian, blksft,
|
||||||
grub_zfs_to_cpu16 (le->le_name_chunk,
|
grub_zfs_to_cpu16 (le->le_name_chunk,
|
||||||
endian),
|
endian),
|
||||||
|
@ -2465,6 +2531,12 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
val_length = ((int) le->le_value_length
|
val_length = ((int) le->le_value_length
|
||||||
* (int) le->le_int_size);
|
* (int) le->le_int_size);
|
||||||
val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
|
val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
grub_free (l);
|
||||||
|
grub_free (buf);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
if (zap_leaf_array_get (l, endian, blksft,
|
if (zap_leaf_array_get (l, endian, blksft,
|
||||||
grub_zfs_to_cpu16 (le->le_value_chunk,
|
grub_zfs_to_cpu16 (le->le_value_chunk,
|
||||||
endian),
|
endian),
|
||||||
|
@ -2536,6 +2608,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_free (zapbuf);
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2606,6 +2679,7 @@ zap_iterate_u64 (dnode_end_t * zap_dnode,
|
||||||
grub_free (zapbuf);
|
grub_free (zapbuf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
grub_free (zapbuf);
|
||||||
grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2636,6 +2710,7 @@ zap_iterate (dnode_end_t * zap_dnode,
|
||||||
if (block_type == ZBT_MICRO)
|
if (block_type == ZBT_MICRO)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected");
|
grub_error (GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected");
|
||||||
|
grub_free (zapbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (block_type == ZBT_HEADER)
|
if (block_type == ZBT_HEADER)
|
||||||
|
@ -2647,6 +2722,7 @@ zap_iterate (dnode_end_t * zap_dnode,
|
||||||
grub_free (zapbuf);
|
grub_free (zapbuf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
grub_free (zapbuf);
|
||||||
grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2720,6 +2796,9 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type,
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE);
|
grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE);
|
||||||
|
if (data->dnode_buf == 0)
|
||||||
|
/* dnbuf not used anymore if data->dnode_mdn malloc failed */
|
||||||
|
grub_free (dnbuf);
|
||||||
buf->endian = endian;
|
buf->endian = endian;
|
||||||
if (type && buf->dn.dn_type != type)
|
if (type && buf->dn.dn_type != type)
|
||||||
return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type");
|
return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type");
|
||||||
|
@ -2872,6 +2951,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
&& ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
&& ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||||
{
|
{
|
||||||
char *sym_value;
|
char *sym_value;
|
||||||
|
grub_size_t sz;
|
||||||
grub_size_t sym_sz;
|
grub_size_t sym_sz;
|
||||||
int free_symval = 0;
|
int free_symval = 0;
|
||||||
char *oldpath = path, *oldpathbuf = path_buf;
|
char *oldpath = path, *oldpathbuf = path_buf;
|
||||||
|
@ -2923,7 +3003,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
break;
|
break;
|
||||||
free_symval = 1;
|
free_symval = 1;
|
||||||
}
|
}
|
||||||
path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
|
||||||
|
if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
|
||||||
|
grub_add (sz, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
|
||||||
|
grub_free (oldpathbuf);
|
||||||
|
if (free_symval)
|
||||||
|
grub_free (sym_value);
|
||||||
|
err = grub_errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = path_buf = grub_malloc (sz);
|
||||||
if (!path_buf)
|
if (!path_buf)
|
||||||
{
|
{
|
||||||
grub_free (oldpathbuf);
|
grub_free (oldpathbuf);
|
||||||
|
@ -2960,6 +3051,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
{
|
{
|
||||||
void *sahdrp;
|
void *sahdrp;
|
||||||
int hdrsize;
|
int hdrsize;
|
||||||
|
grub_size_t sz;
|
||||||
|
bool free_sahdrp = false;
|
||||||
|
|
||||||
if (dnode_path->dn.dn.dn_bonuslen != 0)
|
if (dnode_path->dn.dn.dn_bonuslen != 0)
|
||||||
{
|
{
|
||||||
|
@ -2972,6 +3065,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
|
err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
free_sahdrp = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2993,7 +3087,15 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
+ SA_SIZE_OFFSET),
|
+ SA_SIZE_OFFSET),
|
||||||
dnode_path->dn.endian);
|
dnode_path->dn.endian);
|
||||||
char *oldpath = path, *oldpathbuf = path_buf;
|
char *oldpath = path, *oldpathbuf = path_buf;
|
||||||
path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
if (grub_add (sym_sz, grub_strlen (oldpath), &sz) ||
|
||||||
|
grub_add (sz, 1, &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow"));
|
||||||
|
grub_free (oldpathbuf);
|
||||||
|
err = grub_errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = path_buf = grub_malloc (sz);
|
||||||
if (!path_buf)
|
if (!path_buf)
|
||||||
{
|
{
|
||||||
grub_free (oldpathbuf);
|
grub_free (oldpathbuf);
|
||||||
|
@ -3022,6 +3124,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||||
}
|
}
|
||||||
dn_new = dnode_path;
|
dn_new = dnode_path;
|
||||||
}
|
}
|
||||||
|
if (free_sahdrp == true)
|
||||||
|
grub_free (sahdrp);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3263,6 +3368,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||||
filename = 0;
|
filename = 0;
|
||||||
snapname = 0;
|
snapname = 0;
|
||||||
fsname = grub_strdup (fullpath);
|
fsname = grub_strdup (fullpath);
|
||||||
|
if (!fsname)
|
||||||
|
return grub_errno;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3348,6 +3455,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_dprintf ("zfs", "failed here\n");
|
grub_dprintf ("zfs", "failed here\n");
|
||||||
|
grub_free (fsname);
|
||||||
|
grub_free (snapname);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3384,8 +3493,11 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||||
if (!err)
|
if (!err)
|
||||||
err = dnode_get (&(data->mos), headobj, 0,
|
err = dnode_get (&(data->mos), headobj, 0,
|
||||||
&subvol->mdn, data);
|
&subvol->mdn, data);
|
||||||
if (!err && subvol->mdn.dn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET)
|
if (!err && subvol->mdn.dn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET) {
|
||||||
|
grub_free (fsname);
|
||||||
|
grub_free (snapname);
|
||||||
return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type");
|
return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type");
|
||||||
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -3568,6 +3680,7 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
|
||||||
unsigned i;
|
unsigned i;
|
||||||
grub_size_t nelm;
|
grub_size_t nelm;
|
||||||
int elemsize = 0;
|
int elemsize = 0;
|
||||||
|
int sz;
|
||||||
|
|
||||||
found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
|
found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair,
|
||||||
&size, &nelm);
|
&size, &nelm);
|
||||||
|
@ -3602,7 +3715,12 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = grub_zalloc (elemsize + sizeof (grub_uint32_t));
|
if (grub_add (elemsize, sizeof (grub_uint32_t), &sz))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("elemsize overflow"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = grub_zalloc (sz);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
|
grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
|
||||||
|
@ -3678,8 +3796,13 @@ zfs_mount (grub_device_t dev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data->n_devices_allocated = 16;
|
data->n_devices_allocated = 16;
|
||||||
data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
data->devices_attached = grub_calloc (data->n_devices_allocated,
|
||||||
* data->n_devices_allocated);
|
sizeof (data->devices_attached[0]));
|
||||||
|
if (!data->devices_attached)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
data->n_devices_attached = 0;
|
data->n_devices_attached = 0;
|
||||||
err = scan_disk (dev, data, 1, &inserted);
|
err = scan_disk (dev, data, 1, &inserted);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -3853,6 +3976,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
|
||||||
{
|
{
|
||||||
void *sahdrp;
|
void *sahdrp;
|
||||||
int hdrsize;
|
int hdrsize;
|
||||||
|
bool free_sahdrp = false;
|
||||||
|
|
||||||
if (data->dnode.dn.dn_bonuslen != 0)
|
if (data->dnode.dn.dn_bonuslen != 0)
|
||||||
{
|
{
|
||||||
|
@ -3865,6 +3989,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
|
||||||
err = zio_read (bp, data->dnode.endian, &sahdrp, NULL, data);
|
err = zio_read (bp, data->dnode.endian, &sahdrp, NULL, data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
free_sahdrp = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3873,6 +3998,8 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
|
||||||
|
|
||||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||||
file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian);
|
file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian);
|
||||||
|
if (free_sahdrp)
|
||||||
|
grub_free(sahdrp);
|
||||||
}
|
}
|
||||||
else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE)
|
else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||||
{
|
{
|
||||||
|
@ -4058,6 +4185,7 @@ fill_fs_info (struct grub_dirhook_info *info,
|
||||||
{
|
{
|
||||||
void *sahdrp;
|
void *sahdrp;
|
||||||
int hdrsize;
|
int hdrsize;
|
||||||
|
bool free_sahdrp = false;
|
||||||
|
|
||||||
if (dn.dn.dn_bonuslen != 0)
|
if (dn.dn.dn_bonuslen != 0)
|
||||||
{
|
{
|
||||||
|
@ -4070,6 +4198,7 @@ fill_fs_info (struct grub_dirhook_info *info,
|
||||||
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
free_sahdrp = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4080,6 +4209,8 @@ fill_fs_info (struct grub_dirhook_info *info,
|
||||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||||
info->mtimeset = 1;
|
info->mtimeset = 1;
|
||||||
info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||||
|
if (free_sahdrp)
|
||||||
|
grub_free (sahdrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||||
|
@ -4111,6 +4242,7 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
||||||
{
|
{
|
||||||
void *sahdrp;
|
void *sahdrp;
|
||||||
int hdrsize;
|
int hdrsize;
|
||||||
|
bool free_sahdrp = false;
|
||||||
|
|
||||||
if (dn.dn.dn_bonuslen != 0)
|
if (dn.dn.dn_bonuslen != 0)
|
||||||
{
|
{
|
||||||
|
@ -4126,6 +4258,7 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
free_sahdrp = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4138,6 +4271,8 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
||||||
info.mtimeset = 1;
|
info.mtimeset = 1;
|
||||||
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||||
info.case_insensitive = ctx->data->subvol.case_insensitive;
|
info.case_insensitive = ctx->data->subvol.case_insensitive;
|
||||||
|
if (free_sahdrp)
|
||||||
|
grub_free (sahdrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||||
|
@ -4193,6 +4328,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||||
struct grub_dirhook_info info;
|
struct grub_dirhook_info info;
|
||||||
char *name2;
|
char *name2;
|
||||||
int ret;
|
int ret;
|
||||||
|
grub_size_t sz;
|
||||||
|
|
||||||
dnode_end_t mdn;
|
dnode_end_t mdn;
|
||||||
|
|
||||||
|
@ -4213,7 +4349,13 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
name2 = grub_malloc (grub_strlen (name) + 2);
|
if (grub_add (grub_strlen (name), 2, &sz))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow"));
|
||||||
|
|
||||||
|
name2 = grub_malloc (sz);
|
||||||
|
if (!name2)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
name2[0] = '@';
|
name2[0] = '@';
|
||||||
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
|
||||||
ret = ctx->hook (name2, &info, ctx->hook_data);
|
ret = ctx->hook (name2, &info, ctx->hook_data);
|
||||||
|
@ -4342,7 +4484,7 @@ check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct gru
|
||||||
dnode_end_t dn,mosmdn;
|
dnode_end_t dn,mosmdn;
|
||||||
mzap_phys_t* mzp;
|
mzap_phys_t* mzp;
|
||||||
grub_zfs_endian_t endianzap;
|
grub_zfs_endian_t endianzap;
|
||||||
int size;
|
int size, ret;
|
||||||
grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
|
grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
|
||||||
mosmdn.endian=endian;
|
mosmdn.endian=endian;
|
||||||
errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
|
errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
|
||||||
|
@ -4368,7 +4510,9 @@ check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct gru
|
||||||
return errnum;
|
return errnum;
|
||||||
|
|
||||||
size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
|
size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
|
||||||
return mzap_iterate (mzp,endianzap, size, check_feature,NULL);
|
ret = mzap_iterate (mzp,endianzap, size, check_feature,NULL);
|
||||||
|
grub_free(mzp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4424,6 +4568,7 @@ static struct grub_fs grub_zfs_fs = {
|
||||||
GRUB_MOD_INIT (zfs)
|
GRUB_MOD_INIT (zfs)
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE);
|
COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE);
|
||||||
|
grub_zfs_fs.mod = mod;
|
||||||
grub_fs_register (&grub_zfs_fs);
|
grub_fs_register (&grub_zfs_fs);
|
||||||
#ifndef GRUB_UTIL
|
#ifndef GRUB_UTIL
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
|
|
|
@ -379,14 +379,17 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
|
||||||
|
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
|
|
||||||
if (err)
|
if (err) {
|
||||||
|
grub_free (nvlist);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
|
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
|
||||||
if (!poolname)
|
if (!poolname)
|
||||||
{
|
{
|
||||||
if (!grub_errno)
|
if (!grub_errno)
|
||||||
grub_error (GRUB_ERR_BAD_FS, "No poolname found");
|
grub_error (GRUB_ERR_BAD_FS, "No poolname found");
|
||||||
|
grub_free (nvlist);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ gdb.prompt_hook = prompt_hook
|
||||||
|
|
||||||
class IsGrubLoaded (gdb.Function):
|
class IsGrubLoaded (gdb.Function):
|
||||||
"""Return 1 if GRUB has been loaded in memory, otherwise 0.
|
"""Return 1 if GRUB has been loaded in memory, otherwise 0.
|
||||||
The hueristic used is checking if the first 4 bytes of the memory pointed
|
The heuristic used is checking if the first 4 bytes of the memory pointed
|
||||||
to by the _start symbol are not 0. This is true for QEMU on the first run
|
to by the _start symbol are not 0. This is true for QEMU on the first run
|
||||||
of GRUB. This may not be true on physical hardware, where memory is not
|
of GRUB. This may not be true on physical hardware, where memory is not
|
||||||
necessarily cleared on soft reset. This may not also be true in QEMU on
|
necessarily cleared on soft reset. This may not also be true in QEMU on
|
||||||
|
|
|
@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then
|
||||||
@TARGET_STRIP@ --strip-unneeded \
|
@TARGET_STRIP@ --strip-unneeded \
|
||||||
-K grub_mod_init -K grub_mod_fini \
|
-K grub_mod_init -K grub_mod_fini \
|
||||||
-K _grub_mod_init -K _grub_mod_fini \
|
-K _grub_mod_init -K _grub_mod_fini \
|
||||||
-R .note.gnu.gold-version -R .note.GNU-stack \
|
-R .note.GNU-stack \
|
||||||
|
-R .note.gnu.gold-version \
|
||||||
|
-R .note.gnu.property \
|
||||||
-R .gnu.build.attributes \
|
-R .gnu.build.attributes \
|
||||||
|
-R '.llvm*' \
|
||||||
-R .rel.gnu.build.attributes \
|
-R .rel.gnu.build.attributes \
|
||||||
-R .rela.gnu.build.attributes \
|
-R .rela.gnu.build.attributes \
|
||||||
-R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \
|
-R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \
|
||||||
|
|
|
@ -35,7 +35,7 @@ BEGIN {
|
||||||
for (i = 3; i <= NF; i++) {
|
for (i = 3; i <= NF; i++) {
|
||||||
modtab[$2] = modtab[$2] " " $i;
|
modtab[$2] = modtab[$2] " " $i;
|
||||||
}
|
}
|
||||||
}
|
} else if ($1 == "") {} #Skip empty lines
|
||||||
else {
|
else {
|
||||||
printf "error: %u: unrecognized input format\n", NR >"/dev/stderr";
|
printf "error: %u: unrecognized input format\n", NR >"/dev/stderr";
|
||||||
error++;
|
error++;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/kernel.h>
|
#include <grub/kernel.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/safemath.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
|
||||||
char *translation;
|
char *translation;
|
||||||
struct string_descriptor desc;
|
struct string_descriptor desc;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
grub_size_t alloc_sz;
|
||||||
|
|
||||||
internal_position = (off + position * sizeof (desc));
|
internal_position = (off + position * sizeof (desc));
|
||||||
|
|
||||||
|
@ -109,7 +111,10 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
|
||||||
length = grub_cpu_to_le32 (desc.length);
|
length = grub_cpu_to_le32 (desc.length);
|
||||||
offset = grub_cpu_to_le32 (desc.offset);
|
offset = grub_cpu_to_le32 (desc.offset);
|
||||||
|
|
||||||
translation = grub_malloc (length + 1);
|
if (grub_add (length, 1, &alloc_sz))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
translation = grub_malloc (alloc_sz);
|
||||||
if (!translation)
|
if (!translation)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -323,8 +328,8 @@ grub_mofile_open (struct grub_gettext_context *ctx,
|
||||||
for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log;
|
for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log;
|
||||||
ctx->grub_gettext_max_log++);
|
ctx->grub_gettext_max_log++);
|
||||||
|
|
||||||
ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max
|
ctx->grub_gettext_msg_list = grub_calloc (ctx->grub_gettext_max,
|
||||||
* sizeof (ctx->grub_gettext_msg_list[0]));
|
sizeof (ctx->grub_gettext_msg_list[0]));
|
||||||
if (!ctx->grub_gettext_msg_list)
|
if (!ctx->grub_gettext_msg_list)
|
||||||
{
|
{
|
||||||
grub_file_close (fd);
|
grub_file_close (fd);
|
||||||
|
@ -535,6 +540,10 @@ GRUB_MOD_INIT (gettext)
|
||||||
|
|
||||||
GRUB_MOD_FINI (gettext)
|
GRUB_MOD_FINI (gettext)
|
||||||
{
|
{
|
||||||
|
grub_register_variable_hook ("locale_dir", NULL, NULL);
|
||||||
|
grub_register_variable_hook ("secondary_locale_dir", NULL, NULL);
|
||||||
|
grub_register_variable_hook ("lang", NULL, NULL);
|
||||||
|
|
||||||
grub_gettext_delete_list (&main_context);
|
grub_gettext_delete_list (&main_context);
|
||||||
grub_gettext_delete_list (&secondary_context);
|
grub_gettext_delete_list (&secondary_context);
|
||||||
|
|
||||||
|
|
|
@ -553,10 +553,18 @@ init_terminal (grub_gfxmenu_view_t view)
|
||||||
static void
|
static void
|
||||||
init_background (grub_gfxmenu_view_t view)
|
init_background (grub_gfxmenu_view_t view)
|
||||||
{
|
{
|
||||||
|
struct grub_video_bitmap *scaled_bitmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You don't have to scale a raw image if it's not present. This prevents
|
||||||
|
* setting grub_errno and disrupting a command execution.
|
||||||
|
*/
|
||||||
|
if (view->raw_desktop_image == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
if (view->scaled_desktop_image)
|
if (view->scaled_desktop_image)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct grub_video_bitmap *scaled_bitmap;
|
|
||||||
if (view->desktop_image_scale_method ==
|
if (view->desktop_image_scale_method ==
|
||||||
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH)
|
||||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||||
|
|
|
@ -366,6 +366,10 @@ static int dbits = 6; /* bits in base distance lookup table */
|
||||||
lookup of seven bits, the EOB code will be found in that first
|
lookup of seven bits, the EOB code will be found in that first
|
||||||
lookup, and so will not require that too many bits be pulled from
|
lookup, and so will not require that too many bits be pulled from
|
||||||
the stream.
|
the stream.
|
||||||
|
|
||||||
|
Note that NEEDBITS() can fail if the file is corrupt/truncated.
|
||||||
|
The GOTOFAILIFERROR, RETURNIFERROR and RETURN1IFERROR macros can
|
||||||
|
help.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static ush mask_bits[] =
|
static ush mask_bits[] =
|
||||||
|
@ -377,10 +381,14 @@ static ush mask_bits[] =
|
||||||
|
|
||||||
#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<<k;k+=8;}} while (0)
|
#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<<k;k+=8;}} while (0)
|
||||||
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
|
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
|
||||||
|
#define RETURNIFERROR if (grub_errno != GRUB_ERR_NONE) return
|
||||||
|
#define RETURN1IFERROR if (grub_errno != GRUB_ERR_NONE) return 1
|
||||||
|
#define GOTOFAILIFERROR if (grub_errno != GRUB_ERR_NONE) goto fail
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_byte (grub_gzio_t gzio)
|
get_byte (grub_gzio_t gzio)
|
||||||
{
|
{
|
||||||
|
grub_ssize_t bytes_read;
|
||||||
if (gzio->mem_input)
|
if (gzio->mem_input)
|
||||||
{
|
{
|
||||||
if (gzio->mem_input_off < gzio->mem_input_size)
|
if (gzio->mem_input_off < gzio->mem_input_size)
|
||||||
|
@ -393,7 +401,16 @@ get_byte (grub_gzio_t gzio)
|
||||||
|| gzio->inbuf_d == INBUFSIZ))
|
|| gzio->inbuf_d == INBUFSIZ))
|
||||||
{
|
{
|
||||||
gzio->inbuf_d = 0;
|
gzio->inbuf_d = 0;
|
||||||
grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
|
bytes_read = grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
|
||||||
|
/*
|
||||||
|
* Only trigger if we get 0 bytes. If we get negative bytes there should
|
||||||
|
* be an existing GRUB error code that we don't want to overwrite.
|
||||||
|
*/
|
||||||
|
if (bytes_read == 0)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "File is too short");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gzio->inbuf[gzio->inbuf_d++];
|
return gzio->inbuf[gzio->inbuf_d++];
|
||||||
|
@ -507,7 +524,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a table of values in order of bit lengths */
|
/* Make a table of values in order of bit lengths */
|
||||||
grub_memset (v, N_MAX, ARRAY_SIZE (v));
|
grub_memset (v, N_MAX, sizeof (v));
|
||||||
p = b;
|
p = b;
|
||||||
i = 0;
|
i = 0;
|
||||||
do
|
do
|
||||||
|
@ -684,7 +701,7 @@ inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NEEDBITS ((unsigned) gzio->bl);
|
NEEDBITS ((unsigned) gzio->bl); RETURN1IFERROR;
|
||||||
if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
|
if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -696,7 +713,7 @@ inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
}
|
}
|
||||||
DUMPBITS (t->b);
|
DUMPBITS (t->b);
|
||||||
e -= 16;
|
e -= 16;
|
||||||
NEEDBITS (e);
|
NEEDBITS (e); RETURN1IFERROR;
|
||||||
}
|
}
|
||||||
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
|
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
|
||||||
DUMPBITS (t->b);
|
DUMPBITS (t->b);
|
||||||
|
@ -718,7 +735,7 @@ inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get length of block to copy */
|
/* get length of block to copy */
|
||||||
NEEDBITS (e);
|
NEEDBITS (e); RETURN1IFERROR;
|
||||||
n = t->v.n + ((unsigned) b & mask_bits[e]);
|
n = t->v.n + ((unsigned) b & mask_bits[e]);
|
||||||
DUMPBITS (e);
|
DUMPBITS (e);
|
||||||
|
|
||||||
|
@ -729,7 +746,7 @@ inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decode distance of block to copy */
|
/* decode distance of block to copy */
|
||||||
NEEDBITS ((unsigned) gzio->bd);
|
NEEDBITS ((unsigned) gzio->bd); RETURN1IFERROR;
|
||||||
if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
|
if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -741,12 +758,12 @@ inflate_codes_in_window (grub_gzio_t gzio)
|
||||||
}
|
}
|
||||||
DUMPBITS (t->b);
|
DUMPBITS (t->b);
|
||||||
e -= 16;
|
e -= 16;
|
||||||
NEEDBITS (e);
|
NEEDBITS (e); RETURN1IFERROR;
|
||||||
}
|
}
|
||||||
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
|
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
|
||||||
> 16);
|
> 16);
|
||||||
DUMPBITS (t->b);
|
DUMPBITS (t->b);
|
||||||
NEEDBITS (e);
|
NEEDBITS (e); RETURN1IFERROR;
|
||||||
d = w - t->v.n - ((unsigned) b & mask_bits[e]);
|
d = w - t->v.n - ((unsigned) b & mask_bits[e]);
|
||||||
DUMPBITS (e);
|
DUMPBITS (e);
|
||||||
gzio->code_state++;
|
gzio->code_state++;
|
||||||
|
@ -815,10 +832,10 @@ init_stored_block (grub_gzio_t gzio)
|
||||||
DUMPBITS (k & 7);
|
DUMPBITS (k & 7);
|
||||||
|
|
||||||
/* get the length and its complement */
|
/* get the length and its complement */
|
||||||
NEEDBITS (16);
|
NEEDBITS (16); RETURNIFERROR;
|
||||||
gzio->block_len = ((unsigned) b & 0xffff);
|
gzio->block_len = ((unsigned) b & 0xffff);
|
||||||
DUMPBITS (16);
|
DUMPBITS (16);
|
||||||
NEEDBITS (16);
|
NEEDBITS (16); RETURNIFERROR;
|
||||||
if (gzio->block_len != (int) ((~b) & 0xffff))
|
if (gzio->block_len != (int) ((~b) & 0xffff))
|
||||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||||
"the length of a stored block does not match");
|
"the length of a stored block does not match");
|
||||||
|
@ -900,13 +917,13 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
k = gzio->bk;
|
k = gzio->bk;
|
||||||
|
|
||||||
/* read in table lengths */
|
/* read in table lengths */
|
||||||
NEEDBITS (5);
|
NEEDBITS (5); RETURNIFERROR;
|
||||||
nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */
|
nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */
|
||||||
DUMPBITS (5);
|
DUMPBITS (5);
|
||||||
NEEDBITS (5);
|
NEEDBITS (5); RETURNIFERROR;
|
||||||
nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */
|
nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */
|
||||||
DUMPBITS (5);
|
DUMPBITS (5);
|
||||||
NEEDBITS (4);
|
NEEDBITS (4); RETURNIFERROR;
|
||||||
nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */
|
nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */
|
||||||
DUMPBITS (4);
|
DUMPBITS (4);
|
||||||
if (nl > 286 || nd > 30)
|
if (nl > 286 || nd > 30)
|
||||||
|
@ -918,7 +935,7 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
/* read in bit-length-code lengths */
|
/* read in bit-length-code lengths */
|
||||||
for (j = 0; j < nb; j++)
|
for (j = 0; j < nb; j++)
|
||||||
{
|
{
|
||||||
NEEDBITS (3);
|
NEEDBITS (3); RETURNIFERROR;
|
||||||
ll[bitorder[j]] = (unsigned) b & 7;
|
ll[bitorder[j]] = (unsigned) b & 7;
|
||||||
DUMPBITS (3);
|
DUMPBITS (3);
|
||||||
}
|
}
|
||||||
|
@ -947,7 +964,7 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
|
|
||||||
while ((unsigned) i < n)
|
while ((unsigned) i < n)
|
||||||
{
|
{
|
||||||
NEEDBITS ((unsigned) gzio->bl);
|
NEEDBITS ((unsigned) gzio->bl); GOTOFAILIFERROR;
|
||||||
j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
|
j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
|
||||||
DUMPBITS (j);
|
DUMPBITS (j);
|
||||||
j = gzio->td->v.n;
|
j = gzio->td->v.n;
|
||||||
|
@ -955,7 +972,7 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
ll[i++] = l = j; /* save last length in l */
|
ll[i++] = l = j; /* save last length in l */
|
||||||
else if (j == 16) /* repeat last length 3 to 6 times */
|
else if (j == 16) /* repeat last length 3 to 6 times */
|
||||||
{
|
{
|
||||||
NEEDBITS (2);
|
NEEDBITS (2); GOTOFAILIFERROR;
|
||||||
j = 3 + ((unsigned) b & 3);
|
j = 3 + ((unsigned) b & 3);
|
||||||
DUMPBITS (2);
|
DUMPBITS (2);
|
||||||
if ((unsigned) i + j > n)
|
if ((unsigned) i + j > n)
|
||||||
|
@ -968,7 +985,7 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
}
|
}
|
||||||
else if (j == 17) /* 3 to 10 zero length codes */
|
else if (j == 17) /* 3 to 10 zero length codes */
|
||||||
{
|
{
|
||||||
NEEDBITS (3);
|
NEEDBITS (3); GOTOFAILIFERROR;
|
||||||
j = 3 + ((unsigned) b & 7);
|
j = 3 + ((unsigned) b & 7);
|
||||||
DUMPBITS (3);
|
DUMPBITS (3);
|
||||||
if ((unsigned) i + j > n)
|
if ((unsigned) i + j > n)
|
||||||
|
@ -983,7 +1000,7 @@ init_dynamic_block (grub_gzio_t gzio)
|
||||||
else
|
else
|
||||||
/* j == 18: 11 to 138 zero length codes */
|
/* j == 18: 11 to 138 zero length codes */
|
||||||
{
|
{
|
||||||
NEEDBITS (7);
|
NEEDBITS (7); GOTOFAILIFERROR;
|
||||||
j = 11 + ((unsigned) b & 0x7f);
|
j = 11 + ((unsigned) b & 0x7f);
|
||||||
DUMPBITS (7);
|
DUMPBITS (7);
|
||||||
if ((unsigned) i + j > n)
|
if ((unsigned) i + j > n)
|
||||||
|
@ -1049,12 +1066,12 @@ get_new_block (grub_gzio_t gzio)
|
||||||
k = gzio->bk;
|
k = gzio->bk;
|
||||||
|
|
||||||
/* read in last block bit */
|
/* read in last block bit */
|
||||||
NEEDBITS (1);
|
NEEDBITS (1); RETURNIFERROR;
|
||||||
gzio->last_block = (int) b & 1;
|
gzio->last_block = (int) b & 1;
|
||||||
DUMPBITS (1);
|
DUMPBITS (1);
|
||||||
|
|
||||||
/* read in block type */
|
/* read in block type */
|
||||||
NEEDBITS (2);
|
NEEDBITS (2); RETURNIFERROR;
|
||||||
gzio->block_type = (unsigned) b & 3;
|
gzio->block_type = (unsigned) b & 3;
|
||||||
DUMPBITS (2);
|
DUMPBITS (2);
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ptr = (grub_unaligned_uint64_t *) (xsdt + 1);
|
ptr = (grub_unaligned_uint64_t *) (xsdt + 1);
|
||||||
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
|
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint64_t);
|
||||||
for (; s; s--, ptr++)
|
for (; s; s--, ptr++)
|
||||||
{
|
{
|
||||||
struct grub_acpi_table_header *tbl;
|
struct grub_acpi_table_header *tbl;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue