forked from open-education-hub/operating-systems
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
data/lab/arena: Add access-counter challenge
A challenge to exercise mprotect() and an intro in SIGSEGV handling. Signed-off-by: Razvan Deaconescu <[email protected]>
- Loading branch information
Showing
15 changed files
with
627 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
content/chapters/data/lab/solution/access-counter/src/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
CFLAGS ?= -Wall -Wextra | ||
CPPFLAGS ?= -I../utils | ||
|
||
.PHONY: all clean | ||
|
||
all: access_counter.o ../utils/log/log.o | ||
|
||
access_counter.o: access_counter.c ../utils/utils.h ../utils/log/log.h | ||
|
||
../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h | ||
|
||
clean: | ||
-rm -f access_counter.o ../utils/log/log.o | ||
-rm -f *~ |
96 changes: 96 additions & 0 deletions
96
content/chapters/data/lab/solution/access-counter/src/access_counter.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <signal.h> | ||
#include <sys/mman.h> | ||
|
||
#include "utils.h" | ||
|
||
struct page_info { | ||
int prot; | ||
void *start; | ||
}; | ||
|
||
unsigned long counter; | ||
|
||
#define MAX_PAGES 16 | ||
static struct page_info pages[MAX_PAGES]; | ||
static size_t num_pages = 0; | ||
|
||
/* This is useful for filling the contents when execution rights are provided. */ | ||
static void do_nothing(void) | ||
{ | ||
} | ||
|
||
/* | ||
* The actual SIGSEVG handler. | ||
*/ | ||
static void access_handler(int signum, siginfo_t *si, void *arg) | ||
{ | ||
long page_size = sysconf(_SC_PAGESIZE); | ||
void *start; | ||
int rc; | ||
unsigned int i; | ||
|
||
log_debug("Enter handler"); | ||
|
||
counter++; | ||
|
||
if (signum != SIGSEGV) { | ||
fprintf(stderr, "Unable to handle signal %d (%s)\n", signum, strsignal(signum)); | ||
return; | ||
} | ||
|
||
/* TODO 2: Obtain page strart address in start variable. */ | ||
start = (void *) ((unsigned long) si->si_addr & ~0xFFFUL); | ||
log_debug("start: %p", start); | ||
|
||
for (i = 0; i < num_pages; i++) | ||
if (pages[i].start == start) | ||
break; | ||
|
||
if (i >= num_pages && i < MAX_PAGES) { | ||
pages[i].start = start; | ||
pages[i].prot = PROT_NONE; | ||
num_pages += 1; | ||
} | ||
|
||
log_debug("i = %u", i); | ||
|
||
/* TODO 21: Update page proctections with mprotect(). */ | ||
switch (pages[i].prot) { | ||
case PROT_NONE: | ||
rc = mprotect(start, page_size, PROT_READ); | ||
DIE(rc < 0, "mprotect"); | ||
pages[i].prot = PROT_READ; | ||
break; | ||
case PROT_READ: | ||
rc = mprotect(start, page_size, PROT_READ | PROT_WRITE); | ||
DIE(rc < 0, "mprotect"); | ||
pages[i].prot = PROT_WRITE; | ||
break; | ||
case PROT_WRITE: | ||
rc = mprotect(start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC); | ||
DIE(rc < 0, "mprotect"); | ||
/* Optimistically copy 64 bytes of code. Should be more than enough. */ | ||
memcpy(start, do_nothing, 64); | ||
pages[i].prot = PROT_EXEC; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void register_sigsegv_handler(void) | ||
{ | ||
struct sigaction sa; | ||
int rc; | ||
|
||
memset(&sa, 0, sizeof(sa)); | ||
sa.sa_sigaction = access_handler; | ||
sa.sa_flags = SA_SIGINFO; | ||
|
||
rc = sigaction (SIGSEGV, &sa, NULL); | ||
DIE(rc < 0, "sigaction"); | ||
} |
7 changes: 7 additions & 0 deletions
7
content/chapters/data/lab/solution/access-counter/src/access_counter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef ACCESS_PRINTER_H_ | ||
#define ACCESS_PRINTER_H_ 1 | ||
|
||
extern unsigned long counter; | ||
void register_sigsegv_handler(void); | ||
|
||
#endif |
14 changes: 14 additions & 0 deletions
14
content/chapters/data/lab/support/access-counter/src/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
CFLAGS ?= -Wall -Wextra | ||
CPPFLAGS ?= -I../utils | ||
|
||
.PHONY: all clean | ||
|
||
all: access_counter.o ../utils/log/log.o | ||
|
||
access_counter.o: access_counter.c ../utils/utils.h ../utils/log/log.h | ||
|
||
../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h | ||
|
||
clean: | ||
-rm -f access_counter.o ../utils/log/log.o | ||
-rm -f *~ |
73 changes: 73 additions & 0 deletions
73
content/chapters/data/lab/support/access-counter/src/access_counter.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <signal.h> | ||
#include <sys/mman.h> | ||
|
||
#include "utils.h" | ||
|
||
struct page_info { | ||
int prot; | ||
void *start; | ||
}; | ||
|
||
unsigned long counter; | ||
|
||
#define MAX_PAGES 16 | ||
static struct page_info pages[MAX_PAGES]; | ||
static size_t num_pages = 0; | ||
|
||
/* This is useful for filling the contents when execution rights are provided. */ | ||
static void do_nothing(void) | ||
{ | ||
} | ||
|
||
/* | ||
* The actual SIGSEVG handler. | ||
*/ | ||
static void access_handler(int signum, siginfo_t *si, void *arg) | ||
{ | ||
long page_size = sysconf(_SC_PAGESIZE); | ||
void *start; | ||
int rc; | ||
unsigned int i; | ||
|
||
log_debug("Enter handler"); | ||
|
||
counter++; | ||
|
||
if (signum != SIGSEGV) { | ||
fprintf(stderr, "Unable to handle signal %d (%s)\n", signum, strsignal(signum)); | ||
return; | ||
} | ||
|
||
/* TODO: Obtain page strart address in start variable. */ | ||
|
||
for (i = 0; i < num_pages; i++) | ||
if (pages[i].start == start) | ||
break; | ||
|
||
if (i >= num_pages && i < MAX_PAGES) { | ||
pages[i].start = start; | ||
pages[i].prot = PROT_NONE; | ||
num_pages += 1; | ||
} | ||
|
||
log_debug("i = %u", i); | ||
|
||
/* TODO: Update page proctections with mprotect(). */ | ||
} | ||
|
||
void register_sigsegv_handler(void) | ||
{ | ||
struct sigaction sa; | ||
int rc; | ||
|
||
memset(&sa, 0, sizeof(sa)); | ||
sa.sa_sigaction = access_handler; | ||
sa.sa_flags = SA_SIGINFO; | ||
|
||
rc = sigaction (SIGSEGV, &sa, NULL); | ||
DIE(rc < 0, "sigaction"); | ||
} |
7 changes: 7 additions & 0 deletions
7
content/chapters/data/lab/support/access-counter/src/access_counter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef ACCESS_PRINTER_H_ | ||
#define ACCESS_PRINTER_H_ 1 | ||
|
||
extern unsigned long counter; | ||
void register_sigsegv_handler(void); | ||
|
||
#endif |
1 change: 1 addition & 0 deletions
1
content/chapters/data/lab/support/access-counter/tests/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/test |
44 changes: 44 additions & 0 deletions
44
content/chapters/data/lab/support/access-counter/tests/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
SRC_PATH ?= ../src | ||
FULL_SRC_PATH = $(realpath $(SRC_PATH)) | ||
CPPFLAGS = -I. -I$(realpath $(SRC_PATH)) -I../utils | ||
CFLAGS = -Wall -Wextra | ||
# Remove the line below to disable debugging support. | ||
CFLAGS += -g -O0 | ||
|
||
SRCS = $(wildcard test*.c) | ||
OBJS = $(patsubst %.c,%.o,$(SRCS)) | ||
EXECS = $(patsubst %.c,%,$(SRCS)) | ||
|
||
|
||
.PHONY: all src check lint clean | ||
|
||
all: src $(EXECS) | ||
|
||
$(EXECS): %:%.o graded_test.o $(SRC_PATH)/access_counter.o ../utils/log/log.o | src | ||
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) | ||
|
||
$(OBJS): %.o:%.c graded_test.h | ||
|
||
graded_test.o: graded_test.c graded_test.h | ||
|
||
../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h | ||
|
||
src: | ||
make -C $(FULL_SRC_PATH) | ||
|
||
check: | ||
make -C $(FULL_SRC_PATH) clean | ||
make clean | ||
make -i SRC_PATH=$(FULL_SRC_PATH) | ||
./run_all_tests.sh | ||
|
||
lint: | ||
-cd .. && checkpatch.pl -f src/*.c tests/*.c tests/*/*.c | ||
-cd .. && checkpatch.pl -f checker/*.sh tests/*.sh | ||
-cd .. && cpplint --recursive src/ tests/ checker/ | ||
-cd .. && shellcheck checker/*.sh tests/*.sh | ||
|
||
clean: | ||
-rm -f *~ | ||
-rm -f graded_test.o $(OBJS) | ||
-rm -f $(EXECS) |
Oops, something went wrong.