Fix possible leaks in blockwise read/write code.

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
This commit is contained in:
Milan Broz
2011-04-18 10:52:15 +00:00
parent 5d2205a2f8
commit 231a2e932d
4 changed files with 70 additions and 45 deletions

View 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,

View 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,

View 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;
}

View 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;
memcpy(frontPadBuf+frontHang, buf, innerCount);
if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
goto out;
lseek(fd, offset - frontHang, SEEK_SET);
r = write(fd,frontPadBuf,bsize);
if(r < 0) return -1;
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);
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)