Commit 609e03d4 authored by Julius Plenz's avatar Julius Plenz

Block all signals during store_pageinfo() and free_unclaimed_pages()

The friendly folks at #musl again: 21:34 < dalias> the cheap way around this problem is to block signals for the entire duration of the unsafe operation 21:35 < dalias> formally (by the rules of the standard) this is not sufficient 21:35 < dalias> because formally it's not just calling pthread_mutex_lock again on the same mutex while the first call is interrupted that's undefined 21:36 < dalias> it's calling ANY unsafe function while ANY unsafe function (the same or otherwise) with any argument (e.g. not necessarily the same mutex) that gives undefined behavior 21:38 < dalias> but real-world-implementations don't have this maximum theoretical degree of unsafety 21:38 < dalias> so the approach i described (just ensuring your functions don't interrupt themselves or each other) should be enough to make them safe
parent e979b3dd
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <assert.h> #include <assert.h>
#include <signal.h>
#include "fcntl_helpers.h" #include "fcntl_helpers.h"
...@@ -326,9 +327,13 @@ static void store_pageinfo(int fd) ...@@ -326,9 +327,13 @@ static void store_pageinfo(int fd)
struct stat st; struct stat st;
void *file = NULL; void *file = NULL;
unsigned char *pageinfo = NULL; unsigned char *pageinfo = NULL;
sigset_t mask, old_mask;
sigfillset(&mask);
sigprocmask(SIG_BLOCK, &mask, &old_mask);
if(fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) if(fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))
return; goto restoresigset;
/* Hint we'll be using this file only once; /* Hint we'll be using this file only once;
* the Linux kernel will currently ignore this */ * the Linux kernel will currently ignore this */
...@@ -340,7 +345,7 @@ static void store_pageinfo(int fd) ...@@ -340,7 +345,7 @@ static void store_pageinfo(int fd)
; ;
if(i == max_fds) { if(i == max_fds) {
pthread_mutex_unlock(&lock); pthread_mutex_unlock(&lock);
return; /* no space! */ goto restoresigset; /* no space! */
} }
fds[i].fd = fd; fds[i].fd = fd;
pthread_mutex_unlock(&lock); pthread_mutex_unlock(&lock);
...@@ -351,7 +356,7 @@ static void store_pageinfo(int fd) ...@@ -351,7 +356,7 @@ static void store_pageinfo(int fd)
fds[i].size = 0; fds[i].size = 0;
fds[i].nr_pages = 0; fds[i].nr_pages = 0;
fds[i].info = NULL; fds[i].info = NULL;
return; goto restoresigset;
} }
fds[i].size = st.st_size; fds[i].size = st.st_size;
...@@ -368,7 +373,7 @@ static void store_pageinfo(int fd) ...@@ -368,7 +373,7 @@ static void store_pageinfo(int fd)
fds[i].info = pageinfo; fds[i].info = pageinfo;
munmap(file, st.st_size); munmap(file, st.st_size);
return; goto restoresigset;
cleanup: cleanup:
fds[i].fd = -1; fds[i].fd = -1;
...@@ -376,23 +381,32 @@ static void store_pageinfo(int fd) ...@@ -376,23 +381,32 @@ static void store_pageinfo(int fd)
free(pageinfo); free(pageinfo);
if(file) if(file)
munmap(file, st.st_size); munmap(file, st.st_size);
restoresigset:
sigprocmask(SIG_SETMASK, &old_mask, NULL);
return;
} }
static void free_unclaimed_pages(int fd) static void free_unclaimed_pages(int fd)
{ {
int i, j; int i, j;
int start; int start;
sigset_t mask, old_mask;
if(fd == -1) if(fd == -1)
return; return;
sigfillset(&mask);
sigprocmask(SIG_BLOCK, &mask, &old_mask);
pthread_mutex_lock(&lock); pthread_mutex_lock(&lock);
for(i = 0; i < max_fds; i++) for(i = 0; i < max_fds; i++)
if(fds[i].fd == fd) if(fds[i].fd == fd)
break; break;
pthread_mutex_unlock(&lock); pthread_mutex_unlock(&lock);
if(i == max_fds) if(i == max_fds)
return; /* not found */ goto restoresigset; /* not found */
sync_if_writable(fd); sync_if_writable(fd);
...@@ -411,4 +425,7 @@ static void free_unclaimed_pages(int fd) ...@@ -411,4 +425,7 @@ static void free_unclaimed_pages(int fd)
free(fds[i].info); free(fds[i].info);
fds[i].fd = -1; fds[i].fd = -1;
restoresigset:
sigprocmask(SIG_SETMASK, &old_mask, NULL);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment