#include "config.h"
#include "SyscallPolicy.h"
#if ENABLE(SECCOMP_FILTERS)
#include "WebProcessCreationParameters.h"
#include <libgen.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
namespace WebKit {
static String removeTrailingSlash(const String& path)
{
if (path.endsWith('/'))
return path.left(path.length() - 1);
return path;
}
bool SyscallPolicy::hasPermissionForPath(const char* path, Permission permission) const
{
ASSERT(m_directoryPermission.contains("/"));
if (permission == NotAllowed)
return false;
char* basePath = strdup(path);
char* canonicalPath = canonicalize_file_name(basePath);
while (canonicalPath) {
struct stat pathStat;
if (stat(canonicalPath, &pathStat) == -1) {
free(basePath);
free(canonicalPath);
return false;
}
if (S_ISDIR(pathStat.st_mode))
break;
PermissionMap::const_iterator policy = m_filePermission.find(String(canonicalPath));
if (policy != m_filePermission.end()) {
free(basePath);
free(canonicalPath);
return (permission & policy->value) == permission;
}
free(canonicalPath);
canonicalPath = 0;
}
while (!canonicalPath) {
char* currentBaseDirectory = dirname(basePath);
canonicalPath = canonicalize_file_name(currentBaseDirectory);
}
PermissionMap::const_iterator policy = m_directoryPermission.find(String(canonicalPath));
while (policy == m_directoryPermission.end()) {
char* currentBaseDirectory = dirname(canonicalPath);
policy = m_directoryPermission.find(String(currentBaseDirectory));
}
free(basePath);
free(canonicalPath);
return (permission & policy->value) == permission;
}
void SyscallPolicy::addFilePermission(const String& path, Permission permission)
{
ASSERT(!path.isEmpty() && path.startsWith('/') && !path.endsWith('/') && !path.contains("//"));
m_filePermission.set(path, permission);
}
void SyscallPolicy::addDirectoryPermission(const String& path, Permission permission)
{
ASSERT(path.startsWith('/') && !path.contains("//") && (path.length() == 1 || !path.endsWith('/')));
m_directoryPermission.set(path, permission);
}
void SyscallPolicy::addDefaultWebProcessPolicy(const WebProcessCreationParameters& parameters)
{
if (!parameters.applicationCacheDirectory.isEmpty())
addDirectoryPermission(removeTrailingSlash(parameters.applicationCacheDirectory), ReadAndWrite);
if (!parameters.webSQLDatabaseDirectory.isEmpty())
addDirectoryPermission(removeTrailingSlash(parameters.webSQLDatabaseDirectory), ReadAndWrite);
if (!parameters.diskCacheDirectory.isEmpty())
addDirectoryPermission(removeTrailingSlash(parameters.diskCacheDirectory), ReadAndWrite);
if (!parameters.cookieStorageDirectory.isEmpty())
addDirectoryPermission(removeTrailingSlash(parameters.cookieStorageDirectory), ReadAndWrite);
#if USE(SOUP)
if (!parameters.cookiePersistentStoragePath.isEmpty())
addDirectoryPermission(removeTrailingSlash(parameters.cookiePersistentStoragePath), ReadAndWrite);
#endif
addDirectoryPermission(ASCIILiteral("/"), NotAllowed);
addDirectoryPermission(ASCIILiteral("/lib"), Read);
addDirectoryPermission(ASCIILiteral("/lib32"), Read);
addDirectoryPermission(ASCIILiteral("/lib64"), Read);
addDirectoryPermission(ASCIILiteral("/usr/lib"), Read);
addDirectoryPermission(ASCIILiteral("/usr/lib32"), Read);
addDirectoryPermission(ASCIILiteral("/usr/lib64"), Read);
addDirectoryPermission(ASCIILiteral("/usr/share"), Read);
addDirectoryPermission(ASCIILiteral("/etc/ssl/certs"), Read);
addDirectoryPermission(ASCIILiteral("/etc/fonts"), Read);
addDirectoryPermission(ASCIILiteral("/var/cache/fontconfig"), Read);
addDirectoryPermission(ASCIILiteral("/dev"), ReadAndWrite);
addDirectoryPermission(ASCIILiteral("/tmp"), ReadAndWrite);
addDirectoryPermission(ASCIILiteral("/proc/") + String::number(getpid()), ReadAndWrite);
addDirectoryPermission(ASCIILiteral("/run/shm"), ReadAndWrite);
addFilePermission(ASCIILiteral("/etc/gai.conf"), Read);
addFilePermission(ASCIILiteral("/etc/host.conf"), Read);
addFilePermission(ASCIILiteral("/etc/hosts"), Read);
addFilePermission(ASCIILiteral("/etc/localtime"), Read);
addFilePermission(ASCIILiteral("/etc/nsswitch.conf"), Read);
addFilePermission(ASCIILiteral("/etc/resolv.conf"), Read);
addFilePermission(ASCIILiteral("/run/resolvconf/resolv.conf"), Read);
addFilePermission(ASCIILiteral("/etc/group"), Read);
addFilePermission(ASCIILiteral("/etc/passwd"), Read);
addFilePermission(ASCIILiteral("/etc/ld.so.cache"), Read);
addFilePermission(ASCIILiteral("/proc/cpuinfo"), Read);
addFilePermission(ASCIILiteral("/proc/filesystems"), Read);
addFilePermission(ASCIILiteral("/proc/meminfo"), Read);
addFilePermission(ASCIILiteral("/proc/stat"), Read);
addFilePermission(ASCIILiteral("/var/lib/dbus/machine-id"), Read);
addDirectoryPermission("/run/user/" + String::number(getuid()), ReadAndWrite);
addFilePermission(ASCIILiteral("/sys/fs/cgroup/memory/memory.pressure_level"), Read);
addFilePermission(ASCIILiteral("/sys/fs/cgroup/memory/cgroup.event_control"), Read);
char* homeDir = getenv("HOME");
if (homeDir) {
addFilePermission(String::fromUTF8(homeDir) + "/.Xauthority", Read);
}
char* dataHomeDir = getenv("XDG_DATA_HOME");
if (dataHomeDir)
addDirectoryPermission(String::fromUTF8(dataHomeDir) + "/mime", Read);
else if (homeDir)
addDirectoryPermission(String::fromUTF8(homeDir) + "/.local/share/mime", Read);
#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
addDirectoryPermission(ASCIILiteral("/var/tmp"), ReadAndWrite);
addFilePermission(ASCIILiteral("/etc/drirc"), Read);
if (homeDir)
addFilePermission(String::fromUTF8(homeDir) + "/.drirc", Read);
addDirectoryPermission(ASCIILiteral("/etc/udev"), Read);
addDirectoryPermission(ASCIILiteral("/run/udev"), Read);
addDirectoryPermission(ASCIILiteral("/sys/bus"), Read);
addDirectoryPermission(ASCIILiteral("/sys/class"), Read);
addDirectoryPermission(ASCIILiteral("/sys/devices"), Read);
#endif
if (homeDir)
addDirectoryPermission(String::fromUTF8(homeDir) + "/.nv", ReadAndWrite);
}
}
#endif // ENABLE(SECCOMP_FILTERS)