aboutsummaryrefslogtreecommitdiffstats
path: root/webserver
diff options
context:
space:
mode:
Diffstat (limited to 'webserver')
-rwxr-xr-xwebserver10
1 files changed, 4 insertions, 6 deletions
diff --git a/webserver b/webserver
index 21486ae..211f646 100755
--- a/webserver
+++ b/webserver
@@ -38,6 +38,7 @@ use warnings;
# not a problem since FD can be bound as root prior to the execve(2).
use Errno 'EINTR';
+use Fcntl qw/O_NOFOLLOW O_RDONLY/;
use Socket qw/AF_UNIX AF_INET AF_INET6/;
# Untaint and fdopen(3) the listening socket
@@ -91,12 +92,9 @@ while (1) {
while (defined (my $h = $conn->getline())) { last if $h eq "\r\n" };
my ($status_line, $content_type, $content);
- if ($req =~ /\A\Q$ROOT\E\/([A-Za-z0-9_\-]+)\z/ and
- ! -l $1 and -f _) { # reuse previous stat structure and save a syscall
- # XXX calling lstat(2) before open(2) is racy; if O_NOFOLLOW was
- # exposed to perl we would instead use it and later fstat(2) the
- # file descriptor
- if (open my $fh, '<', $1) { # only open files in the cwd
+ if ($req =~ /\A\Q$ROOT\E\/([A-Za-z0-9_\-]+)\z/ and -f $1) {
+ # only open files in the cwd, and refuse to follow symlinks
+ if (sysopen(my $fh, $1, O_NOFOLLOW|O_RDONLY)) {
($status_line, $content_type) = ('200 OK', 'application/jose+json');
$content = do { local $/ = undef; $fh->getline() };
$fh->close() or die "close: $!";