diff options
author | Karel Zak | 2017-03-13 15:20:56 +0100 |
---|---|---|
committer | Karel Zak | 2017-03-13 15:20:56 +0100 |
commit | b2b5292541d08a9c0236c27a79e62acd49a3aaa1 (patch) | |
tree | 39c99a51cb05dd5c03b8037a30a561079af26fe9 /libfdisk/src/dos.c | |
parent | docs: improve boilerplate.c options example (diff) | |
download | kernel-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.c | 87 |
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) |