mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
86
lib/utils.c
86
lib/utils.c
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user