]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: fix potentially NULL pointer usage
authorKarel Zak <kzak@redhat.com>
Mon, 13 Mar 2017 14:20:56 +0000 (15:20 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 13 Mar 2017 14:20:56 +0000 (15:20 +0100)
Reported-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/dos.c
libfdisk/src/partition.c

index 11946b38cbb262e5d28e9f2bbc935d7400cbe274..39e42e3e6c89b6b2e4febfb8e24aa6e5c34ec74e 100644 (file)
@@ -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)
index 1e8c1eb32862114ff92fa1f5624986542bf438d6..4017096a82540c5d6e2e33055bb4cb77401a1659 100644 (file)
@@ -1243,6 +1243,10 @@ int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
 
        if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) {
                xpa = __copy_partition(pa);
+               if (!xpa) {
+                       rc = -ENOMEM;
+                       goto done;
+               }
                xpa->movestart = 0;
                xpa->resize = 0;
                FDISK_INIT_UNDEF(xpa->size);