Fix possible leaks in blockwise read/write code.
authorMilan Broz <gmazyland@gmail.com>
Mon, 18 Apr 2011 10:52:15 +0000 (10:52 +0000)
committerMilan Broz <gmazyland@gmail.com>
Mon, 18 Apr 2011 10:52:15 +0000 (10:52 +0000)
Fix lseek_write blockwise function (not used in that mode anyway).

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@511 36d66b0a-2a48-0410-832c-cd162a569da5

lib/internal.h
lib/luks1/keyencryption.c
lib/luks1/keymanage.c
lib/utils.c

index 6ffae93..821c383 100644 (file)
@@ -92,9 +92,9 @@ int dm_resume_and_reinstate_key(const char *name,
                                const char *key);
 
 int sector_size_for_device(const char *device);
-ssize_t write_blockwise(int fd, const void *buf, size_t count);
+ssize_t write_blockwise(int fd, void *buf, size_t count);
 ssize_t read_blockwise(int fd, void *_buf, size_t count);
-ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offset);
+ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);
 int device_ready(struct crypt_device *cd, const char *device, int mode);
 int get_device_infos(const char *device,
                     int open_exclusive,
index 127f4b8..c37724a 100644 (file)
@@ -193,9 +193,8 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength,
                            unsigned int sector,
                            struct crypt_device *ctx)
 {
-       return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device, sector,
-                                  (ssize_t (*)(int, void *, size_t)) write_blockwise,
-                                  O_RDWR, ctx);
+       return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device,
+                                  sector, write_blockwise, O_RDWR, ctx);
 }
 
 int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
index b854cf4..6c07492 100644 (file)
@@ -764,29 +764,33 @@ static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn)
 
 static int wipe(const char *device, unsigned int from, unsigned int to)
 {
-       int devfd;
+       int devfd, r = 0;
        char *buffer;
-       unsigned int i;
-       unsigned int bufLen = (to - from) * SECTOR_SIZE;
-       int r = 0;
+       unsigned int i, bufLen;
+       ssize_t written;
 
        devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
        if(devfd == -1)
                return -EINVAL;
 
-       buffer = (char *) malloc(bufLen);
+       bufLen = (to - from) * SECTOR_SIZE;
+       buffer = malloc(bufLen);
        if(!buffer) {
                close(devfd);
                return -ENOMEM;
        }
 
        for(i = 0; i < 39; ++i) {
-               if                (i <  5) crypt_random_get(NULL, buffer, bufLen, CRYPT_RND_NORMAL);
+               if                (i <  5) crypt_random_get(NULL, buffer, bufLen,
+                                                           CRYPT_RND_NORMAL);
                else if(i >=  5 && i < 32) wipeSpecial(buffer, bufLen, i - 5);
-               else if(i >= 32 && i < 38) crypt_random_get(NULL, buffer, bufLen, CRYPT_RND_NORMAL);
+               else if(i >= 32 && i < 38) crypt_random_get(NULL, buffer, bufLen,
+                                                           CRYPT_RND_NORMAL);
                else if(i >= 38 && i < 39) memset(buffer, 0xFF, bufLen);
 
-               if(write_lseek_blockwise(devfd, buffer, bufLen, from * SECTOR_SIZE) < 0) {
+               written = write_lseek_blockwise(devfd, buffer, bufLen,
+                                               from * SECTOR_SIZE);
+               if (written < 0 || written != bufLen) {
                        r = -EIO;
                        break;
                }
index 84519ac..af17f8f 100644 (file)
@@ -128,7 +128,7 @@ int sector_size_for_device(const char *device)
        return r;
 }
 
-ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
+ssize_t write_blockwise(int fd, void *orig_buf, size_t count)
 {
        void *hangover_buf, *hangover_buf_base = NULL;
        void *buf, *buf_base = NULL;
@@ -148,7 +148,7 @@ ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
                        goto out;
                memcpy(buf, orig_buf, count);
        } else
-               buf = (void *)orig_buf;
+               buf = orig_buf;
 
        r = write(fd, buf, solid);
        if (r < 0 || r != solid)
@@ -160,26 +160,28 @@ ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
                        goto out;
 
                r = read(fd, hangover_buf, bsize);
-               if(r < 0 || r != bsize) goto out;
+               if (r < 0 || r != bsize)
+                       goto out;
 
                r = lseek(fd, -bsize, SEEK_CUR);
                if (r < 0)
                        goto out;
-               memcpy(hangover_buf, buf + solid, hangover);
+               memcpy(hangover_buf, (char*)buf + solid, hangover);
 
                r = write(fd, hangover_buf, bsize);
-               if(r < 0 || r != bsize) goto out;
-               free(hangover_buf_base);
+               if (r < 0 || r != bsize)
+                       goto out;
        }
        ret = count;
- out:
+out:
+       free(hangover_buf_base);
        if (buf != orig_buf)
                free(buf_base);
        return ret;
 }
 
 ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
-       void *hangover_buf, *hangover_buf_base;
+       void *hangover_buf, *hangover_buf_base = NULL;
        void *buf, *buf_base = NULL;
        int r, hangover, solid, bsize, alignment;
        ssize_t ret = -1;
@@ -210,11 +212,11 @@ ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
                if (r <  0 || r != bsize)
                        goto out;
 
-               memcpy(buf + solid, hangover_buf, hangover);
-               free(hangover_buf_base);
+               memcpy((char *)buf + solid, hangover_buf, hangover);
        }
        ret = count;
- out:
+out:
+       free(hangover_buf_base);
        if (buf != orig_buf) {
                memcpy(orig_buf, buf, count);
                free(buf_base);
@@ -222,41 +224,61 @@ ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
        return ret;
 }
 
-/* 
+/*
  * Combines llseek with blockwise write. write_blockwise can already deal with short writes
  * but we also need a function to deal with short writes at the start. But this information
- * is implicitly included in the read/write offset, which can not be set to non-aligned 
+ * is implicitly included in the read/write offset, which can not be set to non-aligned
  * boundaries. Hence, we combine llseek with write.
  */
+ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset) {
+       char *frontPadBuf;
+       void *frontPadBuf_base = NULL;
+       int r, bsize, frontHang;
+       size_t innerCount = 0;
+       ssize_t ret = -1;
 
-ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offset) {
-       int bsize = sector_size(fd);
-       const char *orig_buf = buf;
-       char frontPadBuf[bsize];
-       int frontHang = offset % bsize;
-       int r;
-       int innerCount = count < bsize ? count : bsize;
-
-       if (bsize < 0)
+       if ((bsize = sector_size(fd)) < 0)
                return bsize;
 
-       lseek(fd, offset - frontHang, SEEK_SET);
-       if(offset % bsize) {
-               r = read(fd,frontPadBuf,bsize);
-               if(r < 0) return -1;
+       frontHang = offset % bsize;
+
+       if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
+               goto out;
+
+       if (frontHang) {
+               frontPadBuf = aligned_malloc(&frontPadBuf_base,
+                                            bsize, get_alignment(fd));
+               if (!frontPadBuf)
+                       goto out;
+
+               r = read(fd, frontPadBuf, bsize);
+               if (r < 0 || r != bsize)
+                       goto out;
+
+               innerCount = bsize - frontHang;
+               if (innerCount > count)
+                       innerCount = count;
 
-               memcpy(frontPadBuf+frontHang, buf, innerCount);
+               memcpy(frontPadBuf + frontHang, buf, innerCount);
 
-               lseek(fd, offset - frontHang, SEEK_SET);
-               r = write(fd,frontPadBuf,bsize);
-               if(r < 0) return -1;
+               if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
+                       goto out;
+
+               r = write(fd, frontPadBuf, bsize);
+               if (r < 0 || r != bsize)
+                       goto out;
 
                buf += innerCount;
                count -= innerCount;
        }
-       if(count <= 0) return buf - orig_buf;
 
-       return write_blockwise(fd, buf, count) + innerCount;
+       ret = count ? write_blockwise(fd, buf, count) : 0;
+       if (ret >= 0)
+               ret += innerCount;
+out:
+       free(frontPadBuf_base);
+
+       return ret;
 }
 
 int device_ready(struct crypt_device *cd, const char *device, int mode)