summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2012-04-30 11:33:13 -0700
committerGerrit <chrome-bot@google.com>2012-05-02 22:34:32 -0700
commit23429d3d782f7506fb4747356974294cce08ac47 (patch)
tree2c98d253f97d92b3c48ea3d87d4375e64f8ea4cd
parent81f704edad78f03deed5ef899a55e9d0c28dd16c (diff)
downloadvboot-23429d3d782f7506fb4747356974294cce08ac47.tar.gz
Let cgpt open devices in read-only mode when possible.
BUG=chromium-os:12430 TEST=manual Running "make; make runtests" in src/platform/vboot_refererence will test this change. Tests for use on a Chromebook are described in the bug report, but will require a USB or SD card that has a physical write-protect switch. Change-Id: I16a67bad3b59bec0981f4064f51fb1a29da65a90 Reviewed-on: https://gerrit.chromium.org/gerrit/21474 Tested-by: Bill Richardson <wfrichar@chromium.org> Commit-Ready: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Richard Barnette <jrbarnette@chromium.org> Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
-rw-r--r--cgpt/cgpt.h4
-rw-r--r--cgpt/cgpt_add.c6
-rw-r--r--cgpt/cgpt_boot.c13
-rw-r--r--cgpt/cgpt_common.c5
-rw-r--r--cgpt/cgpt_create.c2
-rw-r--r--cgpt/cgpt_find.c2
-rw-r--r--cgpt/cgpt_prioritize.c2
-rw-r--r--cgpt/cgpt_repair.c2
-rw-r--r--cgpt/cgpt_show.c4
-rwxr-xr-xtests/run_cgpt_tests.sh23
10 files changed, 47 insertions, 16 deletions
diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h
index 1c809161..6851ded7 100644
--- a/cgpt/cgpt.h
+++ b/cgpt/cgpt.h
@@ -10,6 +10,7 @@
#endif
#define _FILE_OFFSET_BITS 64
+#include <fcntl.h>
#include <features.h>
#include <stdint.h>
#include <stdio.h>
@@ -61,7 +62,8 @@ struct drive {
};
-int DriveOpen(const char *drive_path, struct drive *drive);
+/* mode should be O_RDONLY or O_RDWR */
+int DriveOpen(const char *drive_path, struct drive *drive, int mode);
int DriveClose(struct drive *drive, int update_as_needed);
int CheckValid(const struct drive *drive);
diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c
index e3e1a483..a3d0fb99 100644
--- a/cgpt/cgpt_add.c
+++ b/cgpt/cgpt_add.c
@@ -39,7 +39,7 @@ int cgpt_set_attributes(CgptAddParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
@@ -101,7 +101,7 @@ int cgpt_get_partition_details(CgptAddParams *params) {
if (params == NULL)
return result;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive)) {
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR)) {
Error("Unable to open drive: %s\n", params->drive_name);
return result;
}
@@ -183,7 +183,7 @@ int cgpt_add(CgptAddParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
diff --git a/cgpt/cgpt_boot.c b/cgpt/cgpt_boot.c
index 33c5471c..f8e712d6 100644
--- a/cgpt/cgpt_boot.c
+++ b/cgpt/cgpt_boot.c
@@ -21,7 +21,7 @@ int cgpt_get_boot_partition_number(CgptBootParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
@@ -65,12 +65,17 @@ int cgpt_boot(CgptBootParams *params) {
struct drive drive;
int retval = 1;
int gpt_retval= 0;
+ int mode = O_RDONLY;
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (params->create_pmbr || params->partition || params->bootfile)
+ mode = O_RDWR;
+
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, mode)) {
return CGPT_FAILED;
+ }
if (CGPT_OK != ReadPMBR(&drive)) {
Error("Unable to read PMBR\n");
@@ -135,8 +140,8 @@ int cgpt_boot(CgptBootParams *params) {
GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
printf("%s\n", buf);
- // Write it all out
- if (CGPT_OK == WritePMBR(&drive))
+ // Write it all out, if needed.
+ if (mode == O_RDONLY || CGPT_OK == WritePMBR(&drive))
retval = 0;
done:
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index a5a509b1..d69eb670 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -153,10 +153,11 @@ static int Save(const int fd, const uint8_t *buf,
// Opens a block device or file, loads raw GPT data from it.
+// mode should be O_RDONLY or O_RDWR
//
// Returns CGPT_FAILED if any error happens.
// Returns CGPT_OK if success and information are stored in 'drive'. */
-int DriveOpen(const char *drive_path, struct drive *drive) {
+int DriveOpen(const char *drive_path, struct drive *drive, int mode) {
struct stat stat;
require(drive_path);
@@ -165,7 +166,7 @@ int DriveOpen(const char *drive_path, struct drive *drive) {
// Clear struct for proper error handling.
memset(drive, 0, sizeof(struct drive));
- drive->fd = open(drive_path, O_RDWR | O_LARGEFILE | O_NOFOLLOW);
+ drive->fd = open(drive_path, mode | O_LARGEFILE | O_NOFOLLOW);
if (drive->fd == -1) {
Error("Can't open %s: %s\n", drive_path, strerror(errno));
return CGPT_FAILED;
diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c
index dc25d8fa..8c899d19 100644
--- a/cgpt/cgpt_create.c
+++ b/cgpt/cgpt_create.c
@@ -15,7 +15,7 @@ int cgpt_create(CgptCreateParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR))
return CGPT_FAILED;
// Erase the data
diff --git a/cgpt/cgpt_find.c b/cgpt/cgpt_find.c
index 20070209..345c8310 100644
--- a/cgpt/cgpt_find.c
+++ b/cgpt/cgpt_find.c
@@ -94,7 +94,7 @@ static int do_search(CgptFindParams *params, char *fileName) {
GptEntry *entry;
char partlabel[GPT_PARTNAME_LEN];
- if (CGPT_OK != DriveOpen(fileName, &drive))
+ if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY))
return 0;
if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
diff --git a/cgpt/cgpt_prioritize.c b/cgpt/cgpt_prioritize.c
index 107c00a9..2b3feb06 100644
--- a/cgpt/cgpt_prioritize.c
+++ b/cgpt/cgpt_prioritize.c
@@ -108,7 +108,7 @@ int cgpt_prioritize(CgptPrioritizeParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
diff --git a/cgpt/cgpt_repair.c b/cgpt/cgpt_repair.c
index 96d3fb1c..97beef84 100644
--- a/cgpt/cgpt_repair.c
+++ b/cgpt/cgpt_repair.c
@@ -15,7 +15,7 @@ int cgpt_repair(CgptRepairParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR))
return CGPT_FAILED;
int gpt_retval = GptSanityCheck(&drive.gpt);
diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c
index d4170b1c..f0022a9d 100644
--- a/cgpt/cgpt_show.c
+++ b/cgpt/cgpt_show.c
@@ -186,7 +186,7 @@ int cgpt_get_num_non_empty_partitions(CgptShowParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
@@ -221,7 +221,7 @@ int cgpt_show(CgptShowParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->drive_name, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
index ffd6f68d..8b792b4e 100755
--- a/tests/run_cgpt_tests.sh
+++ b/tests/run_cgpt_tests.sh
@@ -21,6 +21,7 @@ cd "$DIR"
echo "Create an empty file to use as the device..."
NUM_SECTORS=1000
DEV=fake_dev.bin
+rm -f ${DEV}
dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=${NUM_SECTORS} 2>/dev/null
@@ -232,6 +233,28 @@ assert_pri 13 13 14 12 15 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1
$GPT prioritize -i 1 -f ${DEV}
assert_pri 15 15 13 12 14 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1 1 0
+
+# Now make sure that we don't need write access if we're just looking.
+echo "Test read vs read-write access..."
+chmod 0444 ${DEV}
+
+# These should fail
+$GPT create -z ${DEV} 2>/dev/null && error
+$GPT add -i 2 -P 3 ${DEV} 2>/dev/null && error
+$GPT repair ${DEV} 2>/dev/null && error
+$GPT prioritize -i 3 ${DEV} 2>/dev/null && error
+
+# Most 'boot' usage should fail too.
+$GPT boot -p ${DEV} 2>/dev/null && error
+dd if=/dev/zero of=fake_mbr.bin bs=100 count=1 2>/dev/null
+$GPT boot -b fake_mbr.bin ${DEV} 2>/dev/null && error
+$GPT boot -i 2 ${DEV} 2>/dev/null && error
+
+# These should pass
+$GPT boot ${DEV} >/dev/null
+$GPT show ${DEV} >/dev/null
+$GPT find -t kernel ${DEV} >/dev/null
+
echo "Done."
happy "All tests passed."