hack(6): Fix a segfault that occurs when ASLR is enabled
Prior to this change, savenames() would store "objects" in save files as a blob, and restnames() would load it and overwrite "objects". But since objclass::oc_name and oc_descr are pointers to string constants, they would be invalid when the next time the process is spawned, and opening the inventory would crash by dereferencing invalid pointers.
This commit is contained in:
parent
3b7c09b692
commit
9904cea545
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: hack.o_init.c,v 1.14 2011/08/06 20:42:43 dholland Exp $ */
|
||||
/* $NetBSD: hack.o_init.c,v 1.15 2023/07/30 09:23:21 pho Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
|
||||
|
@ -63,7 +63,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: hack.o_init.c,v 1.14 2011/08/06 20:42:43 dholland Exp $");
|
||||
__RCSID("$NetBSD: hack.o_init.c,v 1.15 2023/07/30 09:23:21 pho Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <string.h>
|
||||
|
@ -184,15 +184,21 @@ savenames(int fd)
|
|||
bwrite(fd, bases, sizeof bases);
|
||||
bwrite(fd, objects, sizeof objects);
|
||||
/*
|
||||
* as long as we use only one version of Hack/Quest we need not save
|
||||
* oc_name and oc_descr, but we must save oc_uname for all objects
|
||||
* We must save not only oc_uname but also oc_name and oc_descr,
|
||||
* because they are string constants whose pointer values aren't
|
||||
* peristent when ASLR is enabled.
|
||||
*/
|
||||
for (i = 0; i < SIZE(objects); i++) {
|
||||
if (objects[i].oc_uname) {
|
||||
len = strlen(objects[i].oc_uname) + 1;
|
||||
bwrite(fd, &len, sizeof len);
|
||||
bwrite(fd, objects[i].oc_uname, len);
|
||||
#define SAVE_NAME_FIELD(FIELD) \
|
||||
if (objects[i].FIELD) { \
|
||||
len = strlen(objects[i].FIELD) + 1; \
|
||||
bwrite(fd, &len, sizeof len); \
|
||||
bwrite(fd, objects[i].FIELD, len); \
|
||||
}
|
||||
SAVE_NAME_FIELD(oc_name);
|
||||
SAVE_NAME_FIELD(oc_descr);
|
||||
SAVE_NAME_FIELD(oc_uname);
|
||||
#undef SAVE_NAME_FIELD
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,15 +206,25 @@ void
|
|||
restnames(int fd)
|
||||
{
|
||||
int i;
|
||||
unsigned len;
|
||||
size_t len;
|
||||
mread(fd, bases, sizeof bases);
|
||||
mread(fd, objects, sizeof objects);
|
||||
for (i = 0; i < SIZE(objects); i++)
|
||||
if (objects[i].oc_uname) {
|
||||
mread(fd, &len, sizeof len);
|
||||
objects[i].oc_uname = alloc(len);
|
||||
mread(fd, objects[i].oc_uname, len);
|
||||
for (i = 0; i < SIZE(objects); i++) {
|
||||
#define RESTORE_NAME_FIELD(FIELD) \
|
||||
if (objects[i].FIELD) { \
|
||||
mread(fd, &len, sizeof len); \
|
||||
objects[i].FIELD = alloc(len); \
|
||||
mread(fd, __UNCONST(objects[i].FIELD), len); \
|
||||
}
|
||||
/*
|
||||
* This leaks memory but who cares? Restoration only
|
||||
* happens on the process startup.
|
||||
*/
|
||||
RESTORE_NAME_FIELD(oc_name);
|
||||
RESTORE_NAME_FIELD(oc_descr);
|
||||
RESTORE_NAME_FIELD(oc_uname);
|
||||
#undef RESTORE_NAME_FIELD
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Reference in New Issue