aboutsummaryrefslogtreecommitdiffstats
path: root/arena.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-09 06:47:03 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-09 06:47:03 +0000
commitd20f1d7701fae2cf2f0c4ae7720fea6bd302d415 (patch)
treeae04f9e61d3b6d56220f4deb0b6f766ced403440 /arena.c
parenta5c4ef9ffa36590b5786e2983a95309a49b69bc3 (diff)
downloadlpsm-d20f1d7701fae2cf2f0c4ae7720fea6bd302d415.tar.gz
lpsm-d20f1d7701fae2cf2f0c4ae7720fea6bd302d415.tar.xz
lpsm-d20f1d7701fae2cf2f0c4ae7720fea6bd302d415.zip
Create a Makefile; fix memory-overwrite bug when file_len > requested_len
Diffstat (limited to 'arena.c')
-rw-r--r--arena.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/arena.c b/arena.c
index d7d3c1b..10df925 100644
--- a/arena.c
+++ b/arena.c
@@ -105,7 +105,7 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
{
struct ObjStore *os = objstore_os_struct;
void *page;
- off_t offset;
+ uintptr_t npage, offset;
char *pageinfo;
struct flock lock;
int old_errno = errno;
@@ -127,23 +127,24 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
# endif /* __i386__ */
#endif /* __linux__ */
+ page = (void *)((uintptr_t)siginfo->si_addr & ~(os->pagesize-1));
+ offset = (uintptr_t)page - (uintptr_t)os->arena;
+ npage = (offset >> os->pageshift);
+ pageinfo = os->pageinfo + npage;
+
if ( signal != SIGSEGV || siginfo->si_code != SEGV_ACCERR ||
- ((uintptr_t)siginfo->si_addr - (uintptr_t)os->arena) >= os->arena_len ) {
+ offset >= os->arena_len ) {
struct sigaction dfl;
-
+
dfl.sa_handler = SIG_DFL;
sigemptyset(&dfl.sa_mask);
dfl.sa_flags = SA_ONESHOT;
sigaction(SIGSEGV, &dfl, NULL);
-
+
errno = old_errno;
return; /* Re-take fault */
}
-
- page = (void *)((uintptr_t)siginfo->si_addr & ~(os->pagesize-1));
- offset = (uintptr_t)page - (uintptr_t)os->arena;
- pageinfo = os->pageinfo + (offset >> os->pageshift);
-
+
mprotect(page, os->pagesize, PROT_READ|PROT_WRITE);
switch ( (enum page_status) *pageinfo ) {
@@ -350,7 +351,7 @@ void *objstore_init(char *main_file, char *log_file, size_t *arena_len)
lock.l_len = 0;
while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
file_len = lseek(os->main_fd, 0, SEEK_END);
- if ( len == 0 ) {
+ if ( len < file_len ) {
len = file_len;
}
len = (len + os->pagesize - 1) & ~(os->pagesize - 1);