summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/dos.c
diff options
context:
space:
mode:
authorKarel Zak2017-03-13 15:20:56 +0100
committerKarel Zak2017-03-13 15:20:56 +0100
commitb2b5292541d08a9c0236c27a79e62acd49a3aaa1 (patch)
tree39c99a51cb05dd5c03b8037a30a561079af26fe9 /libfdisk/src/dos.c
parentdocs: improve boilerplate.c options example (diff)
downloadkernel-qcow2-util-linux-b2b5292541d08a9c0236c27a79e62acd49a3aaa1.tar.gz
kernel-qcow2-util-linux-b2b5292541d08a9c0236c27a79e62acd49a3aaa1.tar.xz
kernel-qcow2-util-linux-b2b5292541d08a9c0236c27a79e62acd49a3aaa1.zip
libfdisk: fix potentially NULL pointer usage
Reported-by: Sami Kerola <kerolasa@iki.fi> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/dos.c')
-rw-r--r--libfdisk/src/dos.c87
1 files changed, 73 insertions, 14 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 11946b38c..39e42e3e6 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -249,6 +249,9 @@ static int read_pte(struct fdisk_context *cxt, size_t pno, fdisk_sector_t offset
unsigned char *buf;
struct pte *pe = self_pte(cxt, pno);
+ if (!pe)
+ return -EINVAL;
+
buf = calloc(1, cxt->sector_size);
if (!buf)
return -ENOMEM;
@@ -311,6 +314,7 @@ static void dos_init(struct fdisk_context *cxt)
for (i = 0; i < 4; i++) {
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
pe->pt_entry = mbr_get_partition(cxt->firstsector, i);
pe->ex_entry = NULL;
pe->offset = 0;
@@ -502,6 +506,10 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
l->ext_index = ext;
pex = self_pte(cxt, ext);
+ if (!pex) {
+ DBG(LABEL, ul_debug("DOS: uninitialized pointer to %zu pex", ext));
+ return;
+ }
pex->ex_entry = pex->pt_entry;
p = pex->pt_entry;
@@ -513,8 +521,6 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
DBG(LABEL, ul_debug("DOS: Reading extended %zu", ext));
while (IS_EXTENDED (p->sys_ind)) {
- pe = self_pte(cxt, cxt->label->nparts_max);
-
if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
/* This is not a Linux restriction, but
this program uses arrays of size MAXIMUM_PARTS.
@@ -526,12 +532,18 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
"if you save this partition table."),
cxt->label->nparts_max);
- clear_partition(pre->ex_entry);
- partition_set_changed(cxt,
- cxt->label->nparts_max - 1, 1);
+ if (pre) {
+ clear_partition(pre->ex_entry);
+ partition_set_changed(cxt,
+ cxt->label->nparts_max - 1, 1);
+ }
return;
}
+ pe = self_pte(cxt, cxt->label->nparts_max);
+ if (!pe)
+ return;
+
if (read_pte(cxt, cxt->label->nparts_max, l->ext_offset +
dos_partition_get_start(p)))
return;
@@ -596,7 +608,8 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
/* remove last empty EBR */
pe = self_pte(cxt, cxt->label->nparts_max - 1);
- if (is_cleared_partition(pe->ex_entry) &&
+ if (pe &&
+ is_cleared_partition(pe->ex_entry) &&
is_cleared_partition(pe->pt_entry)) {
DBG(LABEL, ul_debug("DOS: EBR[offset=%ju]: empty, remove", (uintmax_t) pe->offset));
reset_pte(pe);
@@ -610,8 +623,8 @@ static void read_extended(struct fdisk_context *cxt, size_t ext)
for (i = 4; i < cxt->label->nparts_max; i++) {
p = self_partition(cxt, i);
- if (!dos_partition_get_size(p) &&
- (cxt->label->nparts_max > 5 || q->sys_ind)) {
+ if (p && !dos_partition_get_size(p) &&
+ (cxt->label->nparts_max > 5 || (q && q->sys_ind))) {
fdisk_info(cxt, _("omitting empty partition (%zu)"), i+1);
dos_delete_partition(cxt, i);
goto remove; /* numbering changed */
@@ -798,6 +811,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
for (i = 0; i < 4; i++) {
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
if (is_used_partition(pe->pt_entry))
cxt->label->nparts_cur++;
@@ -815,6 +829,7 @@ static int dos_probe_label(struct fdisk_context *cxt)
struct pte *pe = self_pte(cxt, i);
struct fdisk_dos_label *l = self_label(cxt);
+ assert(pe);
if (!mbr_is_valid_magic(pe->sectorbuffer)) {
fdisk_info(cxt, _(
"Invalid flag 0x%02x%02x of EBR (for partition %zu) will "
@@ -843,6 +858,7 @@ static void set_partition(struct fdisk_context *cxt,
assert(!FDISK_IS_UNDEF(start));
assert(!FDISK_IS_UNDEF(stop));
+ assert(pe);
if (doext) {
struct fdisk_dos_label *l = self_label(cxt);
@@ -884,6 +900,7 @@ static fdisk_sector_t get_unused_start(struct fdisk_context *cxt,
fdisk_sector_t lastplusoff;
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
if (start == pe->offset)
start += cxt->first_lba;
lastplusoff = last[i] + ((part_n < 4) ? 0 : cxt->first_lba);
@@ -901,6 +918,7 @@ static void fill_bounds(struct fdisk_context *cxt,
struct pte *pe = self_pte(cxt, 0);
struct dos_partition *p;
+ assert(pe);
for (i = 0; i < cxt->label->nparts_max; pe++,i++) {
p = pe->pt_entry;
if (is_cleared_partition(p) || IS_EXTENDED (p->sys_ind)) {
@@ -1007,6 +1025,7 @@ static fdisk_sector_t get_unused_last(struct fdisk_context *cxt, size_t n,
for (i = 0; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
if (start < pe->offset && limit >= pe->offset)
limit = pe->offset - 1;
if (start < first[i] && limit >= first[i])
@@ -1036,7 +1055,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
sys = pa && pa->type ? pa->type->code : MBR_LINUX_DATA_PARTITION;
- if (is_used_partition(p)) {
+ if (p && is_used_partition(p)) {
fdisk_warnx(cxt, _("Partition %zu is already defined. "
"Delete it before re-adding it."),
n + 1);
@@ -1127,12 +1146,14 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
if (n == 4) {
/* The first EBR is stored at begin of the extended partition */
struct pte *pe = self_pte(cxt, n);
- pe->offset = l->ext_offset;
+ assert(pe);
+ pe->offset = l->ext_offset;
} else if (n > 4) {
/* The second (and another) EBR */
struct pte *pe = self_pte(cxt, n);
+ assert(pe);
pe->offset = start - cxt->first_lba;
if (pe->offset == l->ext_offset) { /* must be corrected */
pe->offset++;
@@ -1235,6 +1256,8 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
set_partition(cxt, n, 0, start, stop, sys, fdisk_partition_is_bootable(pa));
if (n > 4) {
struct pte *pe = self_pte(cxt, n);
+
+ assert(pe);
set_partition(cxt, n - 1, 1, pe->offset, stop,
MBR_DOS_EXTENDED_PARTITION, 0);
}
@@ -1251,6 +1274,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
if (IS_EXTENDED(sys)) {
struct pte *pen = self_pte(cxt, n);
+ assert(pen);
l->ext_index = n;
l->ext_offset = start;
pen->ex_entry = p;
@@ -1277,6 +1301,7 @@ static int add_logical(struct fdisk_context *cxt,
DBG(LABEL, ul_debug("DOS: nparts max: %zu", cxt->label->nparts_max));
pe = self_pte(cxt, cxt->label->nparts_max);
+ assert(pe);
if (!pe->sectorbuffer) {
pe->sectorbuffer = calloc(1, cxt->sector_size);
@@ -1436,8 +1461,9 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
struct pte *pe = self_pte(cxt, i);
p = self_partition(cxt, i);
- if (is_used_partition(p) && !IS_EXTENDED(p->sys_ind)) {
+ if (p && is_used_partition(p) && !IS_EXTENDED(p->sys_ind)) {
check_consistency(cxt, p, i);
+ assert(pe);
if (get_abs_partition_start(pe) < first[i])
fdisk_warnx(cxt, _(
"Partition %zu: bad start-of-data."),
@@ -1470,11 +1496,13 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
fdisk_sector_t e_last;
struct pte *ext_pe = self_pte(cxt, l->ext_index);
+ assert(ext_pe);
e_last = get_abs_partition_end(ext_pe);
for (i = 4; i < cxt->label->nparts_max; i++) {
total++;
p = self_partition(cxt, i);
+ assert(p);
if (!p->sys_ind) {
if (i != 4 || i + 1 < cxt->label->nparts_max)
@@ -1592,6 +1620,7 @@ static int dos_add_partition(struct fdisk_context *cxt,
for (i = 0; i < 4; i++) {
struct dos_partition *p = self_partition(cxt, i);
+ assert(p);
if (is_used_partition(p)) {
fdisk_sector_t start = dos_partition_get_start(p);
if (last + grain <= start)
@@ -1759,6 +1788,8 @@ static int dos_write_disklabel(struct fdisk_context *cxt)
if (!mbr_changed) {
for (i = 0; i < 4; i++) {
struct pte *pe = self_pte(cxt, i);
+
+ assert(pe);
if (pe->changed)
mbr_changed = 1;
}
@@ -1788,6 +1819,7 @@ static int dos_write_disklabel(struct fdisk_context *cxt)
for (i = 4; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
if (!pe->changed || !pe->offset || !pe->sectorbuffer)
continue;
@@ -1821,6 +1853,7 @@ static int dos_locate_disklabel(struct fdisk_context *cxt, int n,
if ((size_t)n - 1 + 4 < cxt->label->nparts_max) {
struct pte *pe = self_pte(cxt, n - 1 + 4);
+ assert(pe);
assert(pe->private_sectorbuffer);
*name = "EBR";
@@ -1847,7 +1880,10 @@ static int wrong_p_order(struct fdisk_context *cxt, size_t *prev)
for (i = 0 ; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
- struct dos_partition *p = pe->pt_entry;
+ struct dos_partition *p;
+
+ assert(pe);
+ p = pe->pt_entry;
if (i == 4) {
last_i = 4;
@@ -1912,7 +1948,10 @@ static int dos_get_partition(struct fdisk_context *cxt, size_t n,
assert(fdisk_is_label(cxt, DOS));
lb = self_label(cxt);
+
pe = self_pte(cxt, n);
+ assert(pe);
+
p = pe->pt_entry;
pa->used = !is_cleared_partition(p);
if (!pa->used)
@@ -1978,7 +2017,11 @@ static int dos_set_partition(struct fdisk_context *cxt, size_t n,
l = self_label(cxt);
p = self_partition(cxt, n);
+
pe = self_pte(cxt, n);
+ if (!pe)
+ return -EINVAL;
+
orgtype = p->sys_ind;
if (pa->type) {
@@ -2058,6 +2101,7 @@ static void print_chain_of_logicals(struct fdisk_context *cxt)
for (i = 4; i < cxt->label->nparts_max; i++) {
struct pte *pe = self_pte(cxt, i);
+ assert(pe);
fprintf(stderr, "#%02zu EBR [%10ju], "
"data[start=%10ju (%10ju), size=%10ju], "
"link[start=%10ju (%10ju), size=%10ju]\n",
@@ -2114,6 +2158,9 @@ again:
struct pte *cur = self_pte(cxt, i),
*nxt = self_pte(cxt, i + 1);
+ assert(cur);
+ assert(nxt);
+
if (get_abs_partition_start(cur) >
get_abs_partition_start(nxt)) {
@@ -2141,8 +2188,11 @@ again:
struct pte *cur = self_pte(cxt, i),
*nxt = self_pte(cxt, i + 1);
+ assert(cur);
+ assert(nxt);
+
fdisk_sector_t noff = nxt->offset - l->ext_offset,
- ooff = dos_partition_get_start(cur->ex_entry);
+ ooff = dos_partition_get_start(cur->ex_entry);
if (noff == ooff)
continue;
@@ -2183,6 +2233,9 @@ static int dos_reorder(struct fdisk_context *cxt)
pei = self_pte(cxt, i);
pek = self_pte(cxt, k);
+ assert(pei);
+ assert(pek);
+
pe = pei->ex_entry;
pei->ex_entry = pek->ex_entry;
pek->ex_entry = pe;
@@ -2218,6 +2271,9 @@ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i)
assert(fdisk_is_label(cxt, DOS));
pe = self_pte(cxt, i);
+ if (!pe)
+ return -EINVAL;
+
p = pe->pt_entry;
if (!is_used_partition(p) || IS_EXTENDED (p->sys_ind)) {
@@ -2236,8 +2292,11 @@ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i)
for (x = 0; x < cxt->label->nparts_max; x++) {
unsigned int end;
struct pte *prev_pe = self_pte(cxt, x);
- struct dos_partition *prev_p = prev_pe->pt_entry;
+ struct dos_partition *prev_p;
+
+ assert(prev_pe);
+ prev_p = prev_pe->pt_entry;
if (!prev_p)
continue;
end = get_abs_partition_start(prev_pe)