Vertaa committeja
	
		
			7 Commitit
		
	
	
		
			feature/ma
			...
			8d685dc581
		
	
	| Tekijä | SHA1 | Päivämäärä | |
|---|---|---|---|
| 8d685dc581 | |||
| ed43f5f700 | |||
| 10f00aeb45 | |||
| 67eb8b6428 | |||
| f26fd19fb4 | |||
| 204a72da1f | |||
| 88816a4015 | 
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CXXFLAGS=-std=c++17 -O0 -g -no-pie -pipe -MMD -Wall -Wextra
 | 
					CXXFLAGS=-std=c++17 -O0 -g -no-pie -pipe -MMD -Wall -Wextra
 | 
				
			||||||
RELEASE_CXXFLAGS=-std=c++17 -O3 -pipe -MMD -Wall -Wextra
 | 
					RELEASE_CXXFLAGS=-std=c++17 -O3 -pipe -MMD -Wall -Wextra
 | 
				
			||||||
LDFLAGS=-lsqlite3 -lpthread -lcrypto -lstdc++fs -lseccomp
 | 
					LDFLAGS=-lsqlite3 -lpthread -lcrypto -lstdc++fs
 | 
				
			||||||
INCLUDEFLAGS=-I submodules/sqlitemoderncpp/hdr -I submodules/cpp-httplib -I submodules/qssb.h
 | 
					INCLUDEFLAGS=-I submodules/sqlitemoderncpp/hdr -I submodules/cpp-httplib -I submodules/qssb.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CXX=g++
 | 
					CXX=g++
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								qswiki.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								qswiki.cpp
									
									
									
									
									
								
							@@ -77,21 +77,21 @@ int main(int argc, char **argv)
 | 
				
			|||||||
		Logger::error() << "Sandbox is not supported, exiting";
 | 
							Logger::error() << "Sandbox is not supported, exiting";
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if(argc < 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::cerr << "no path to config file provided" << std::endl;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						std::string configpath = std::filesystem::absolute(argv[1]).string();
 | 
				
			||||||
	if(!sandbox->enableForInit())
 | 
						if(!sandbox->enableForInit())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Logger::error() << "Sandboxing for init mode could not be activated.";
 | 
							Logger::error() << "Sandboxing for init mode could not be activated.";
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(argc < 2)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		std::cerr << "no path to config file provided" << std::endl;
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	try
 | 
						try
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ConfigReader configreader(argv[1]);
 | 
							ConfigReader configreader(configpath);
 | 
				
			||||||
		Config config = configreader.readConfig();
 | 
							Config config = configreader.readConfig();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// TODO: config.connectiontring only works as long as we only support sqlite of course
 | 
							// TODO: config.connectiontring only works as long as we only support sqlite of course
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,16 +26,26 @@
 | 
				
			|||||||
bool SandboxLinux::enableForInit()
 | 
					bool SandboxLinux::enableForInit()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	umask(0027);
 | 
						umask(0027);
 | 
				
			||||||
	struct qssb_policy policy = {0};
 | 
						struct qssb_policy *policy = qssb_init_policy();
 | 
				
			||||||
	int blacklisted_syscalls[] = {QSSB_SYS(execveat), QSSB_SYS(execve), -1};
 | 
						if(policy == NULL)
 | 
				
			||||||
	policy.blacklisted_syscalls = blacklisted_syscalls;
 | 
					 | 
				
			||||||
	policy.no_new_privs = 1;
 | 
					 | 
				
			||||||
	int result = qssb_enable_policy(&policy);
 | 
					 | 
				
			||||||
	if(result != 0)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Logger::error() << "Failed to install sandboxing policy (init): " << result;
 | 
							Logger::error() << "Failed to init sandboxing policy (init)";
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						policy->namespace_options = QSSB_UNSHARE_USER;
 | 
				
			||||||
 | 
						policy->drop_caps = 0;
 | 
				
			||||||
 | 
						qssb_append_syscall_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, QSSB_SYS(execveat));
 | 
				
			||||||
 | 
						qssb_append_syscall_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, QSSB_SYS(execve));
 | 
				
			||||||
 | 
						qssb_append_syscall_default_policy(policy, QSSB_SYSCALL_ALLOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int result = qssb_enable_policy(policy);
 | 
				
			||||||
 | 
						if(result != 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Logger::error() << "Failed to enable sandboxing policy (init): " << result;
 | 
				
			||||||
 | 
							qssb_free_policy(policy);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						qssb_free_policy(policy);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,28 +54,34 @@ bool SandboxLinux::enablePreWorker(std::vector<std::string> fsPaths)
 | 
				
			|||||||
	std::sort(fsPaths.begin(), fsPaths.end(),
 | 
						std::sort(fsPaths.begin(), fsPaths.end(),
 | 
				
			||||||
			  [](const std::string &a, const std::string &b) { return a.length() < b.length(); });
 | 
								  [](const std::string &a, const std::string &b) { return a.length() < b.length(); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct qssb_path_policy *policies = new qssb_path_policy[fsPaths.size()];
 | 
						struct qssb_policy *policy = qssb_init_policy();
 | 
				
			||||||
 | 
						if(policy == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Logger::error() << "Failed to init sandboxing policy (pre)";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(unsigned int i = 0; i < fsPaths.size(); i++)
 | 
						for(unsigned int i = 0; i < fsPaths.size(); i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		policies[i].next = policies + (i + 1);
 | 
							qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_WRITE, fsPaths[i].c_str());
 | 
				
			||||||
		policies[i].mountpoint = fsPaths[i].c_str();
 | 
					 | 
				
			||||||
		policies[i].policy = QSSB_MOUNT_ALLOW_READ | QSSB_MOUNT_ALLOW_WRITE;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	policies[fsPaths.size() - 1].next = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct qssb_policy policy = {0};
 | 
						policy->namespace_options = QSSB_UNSHARE_MOUNT;
 | 
				
			||||||
	policy.path_policies = policies;
 | 
						policy->drop_caps = 0;
 | 
				
			||||||
	policy.namespace_options |= QSSB_UNSHARE_MOUNT;
 | 
						policy->mount_path_policies_to_chroot = 1;
 | 
				
			||||||
	policy.namespace_options |= QSSB_UNSHARE_USER;
 | 
					
 | 
				
			||||||
	int blacklisted_syscalls[] = {QSSB_SYS(execveat), QSSB_SYS(execve), -1};
 | 
						qssb_append_syscall_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, QSSB_SYS(execveat));
 | 
				
			||||||
	policy.blacklisted_syscalls = blacklisted_syscalls;
 | 
						qssb_append_syscall_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, QSSB_SYS(execve));
 | 
				
			||||||
	int result = qssb_enable_policy(&policy);
 | 
						qssb_append_syscall_default_policy(policy, QSSB_SYSCALL_ALLOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int result = qssb_enable_policy(policy);
 | 
				
			||||||
	if(result != 0)
 | 
						if(result != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Logger::error() << "Failed to install sandboxing policy (preworker): %i" << result;
 | 
							Logger::error() << "Failed to install sandboxing policy (preworker): %i" << result;
 | 
				
			||||||
 | 
							qssb_free_policy(policy);
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	delete[] policies;
 | 
						qssb_free_policy(policy);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,30 +104,35 @@ bool SandboxLinux::supported()
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
bool SandboxLinux::enableForWorker()
 | 
					bool SandboxLinux::enableForWorker()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct qssb_policy policy = {0};
 | 
						struct qssb_policy *policy = qssb_init_policy();
 | 
				
			||||||
	policy.drop_caps = 1;
 | 
						if(policy == NULL)
 | 
				
			||||||
	policy.not_dumpable = 1;
 | 
						{
 | 
				
			||||||
	policy.no_new_privs = 1;
 | 
							Logger::error() << "Failed to init sandboxing policy (worker) ";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						policy->drop_caps = 1;
 | 
				
			||||||
 | 
						policy->not_dumpable = 1;
 | 
				
			||||||
 | 
						policy->no_new_privs = 1;
 | 
				
			||||||
 | 
						policy->namespace_options = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO: as said, a whitelist approach is better. As such, this list is bound to be incomplete in the
 | 
						/* TODO: as said, a whitelist approach is better. As such, this list is bound to be incomplete in the
 | 
				
			||||||
	 * sense that more could be listed here and some critical ones are probably missing */
 | 
						 * sense that more could be listed here and some critical ones are probably missing */
 | 
				
			||||||
	int blacklisted_syscalls[] = {QSSB_SYS(setuid),
 | 
					
 | 
				
			||||||
								  QSSB_SYS(connect),
 | 
						/* TODO: use qssb groups */
 | 
				
			||||||
								  QSSB_SYS(chroot),
 | 
						long blacklisted_syscalls[] = {QSSB_SYS(setuid),	  QSSB_SYS(connect), QSSB_SYS(chroot),	QSSB_SYS(pivot_root),
 | 
				
			||||||
								  QSSB_SYS(pivot_root),
 | 
													   QSSB_SYS(mount),		  QSSB_SYS(setns),	 QSSB_SYS(unshare), QSSB_SYS(ptrace),
 | 
				
			||||||
								  QSSB_SYS(mount),
 | 
													   QSSB_SYS(personality), QSSB_SYS(prctl)};
 | 
				
			||||||
								  QSSB_SYS(setns),
 | 
					
 | 
				
			||||||
								  QSSB_SYS(unshare),
 | 
						qssb_append_syscalls_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, blacklisted_syscalls,
 | 
				
			||||||
								  QSSB_SYS(ptrace),
 | 
													sizeof(blacklisted_syscalls) / sizeof(blacklisted_syscalls[0]));
 | 
				
			||||||
								  QSSB_SYS(personality),
 | 
						qssb_append_syscall_default_policy(policy, QSSB_SYSCALL_ALLOW);
 | 
				
			||||||
								  QSSB_SYS(prctl),
 | 
					
 | 
				
			||||||
								  -1};
 | 
						if(qssb_enable_policy(policy) != 0)
 | 
				
			||||||
	policy.blacklisted_syscalls = blacklisted_syscalls;
 | 
					 | 
				
			||||||
	if(qssb_enable_policy(&policy) != 0)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Logger::error() << "Sandbox: Activation of seccomp blacklist failed!";
 | 
							Logger::error() << "Sandbox: Activation of seccomp blacklist failed!";
 | 
				
			||||||
 | 
							qssb_free_policy(policy);
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						qssb_free_policy(policy);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,24 +25,13 @@ count integer
 | 
				
			|||||||
CREATE TABLE category(id INTEGER PRIMARY KEY, name varchar(255));
 | 
					CREATE TABLE category(id INTEGER PRIMARY KEY, name varchar(255));
 | 
				
			||||||
CREATE TABLE categorymember(id INTEGER PRIMARY KEY, category REFERENCES category(id), page REFERENCES page (id));
 | 
					CREATE TABLE categorymember(id INTEGER PRIMARY KEY, category REFERENCES category(id), page REFERENCES page (id));
 | 
				
			||||||
CREATE INDEX revisionid ON revision (revisionid DESC);
 | 
					CREATE INDEX revisionid ON revision (revisionid DESC);
 | 
				
			||||||
CREATE INDEX pagename ON page (name)
 | 
					CREATE INDEX pagename ON page (name);
 | 
				
			||||||
;
 | 
					CREATE INDEX token ON session (token);
 | 
				
			||||||
CREATE INDEX token ON session (token)
 | 
					CREATE VIRTUAL TABLE search USING fts5(content, page UNINDEXED, content=revision,content_rowid=id);
 | 
				
			||||||
;
 | 
					 | 
				
			||||||
CREATE TRIGGER search_ai AFTER INSERT ON revision BEGIN
 | 
					 | 
				
			||||||
  DELETE FROM search WHERE page = new.page;
 | 
					 | 
				
			||||||
  INSERT INTO search(rowid, content, page) VALUES (new.id, new.content, new.page);
 | 
					 | 
				
			||||||
END;
 | 
					 | 
				
			||||||
CREATE TRIGGER search_au AFTER UPDATE ON revision BEGIN
 | 
					 | 
				
			||||||
  DELETE FROM search WHERE page = old.page;
 | 
					 | 
				
			||||||
  INSERT INTO search(rowid, content, page) VALUES (new.id, new.content, new.page);
 | 
					 | 
				
			||||||
END;
 | 
					 | 
				
			||||||
CREATE VIRTUAL TABLE search USING fts5(content, page UNINDEXED, content=revision,content_rowid=id)
 | 
					 | 
				
			||||||
/* search(content,page) */;
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS 'search_data'(id INTEGER PRIMARY KEY, block BLOB);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS 'search_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID;
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS 'search_docsize'(id INTEGER PRIMARY KEY, sz BLOB);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS 'search_config'(k PRIMARY KEY, v) WITHOUT ROWID;
 | 
					 | 
				
			||||||
CREATE TRIGGER search_ad AFTER DELETE ON revision BEGIN
 | 
					CREATE TRIGGER search_ad AFTER DELETE ON revision BEGIN
 | 
				
			||||||
  INSERT INTO search(search, rowid, content, page) VALUES('delete', old.id, old.content, old.page);
 | 
					  INSERT INTO search(search, rowid, content, page) VALUES('delete', old.id, old.content, old.page);
 | 
				
			||||||
END;
 | 
					END;
 | 
				
			||||||
 | 
					CREATE TRIGGER search_ai AFTER INSERT ON revision BEGIN
 | 
				
			||||||
 | 
					  INSERT INTO search(search, rowid, content, page) SELECT 'delete', id, content, page FROM revision WHERE page = new.page AND revisionid = new.revisionid - 1; 
 | 
				
			||||||
 | 
					  INSERT INTO search(rowid, content, page) VALUES (new.id, new.content, new.page);
 | 
				
			||||||
 | 
					END;
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule submodules/cpp-httplib updated: 63643e6386...d87d0672a8
									
								
							 Submodule submodules/qssb.h updated: 9df2e9ee90...11d64c6fcf
									
								
							@@ -46,6 +46,12 @@ std::string utils::html_xss(std::string_view str)
 | 
				
			|||||||
		case '%':
 | 
							case '%':
 | 
				
			||||||
			result += "%";
 | 
								result += "%";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case '\'':
 | 
				
			||||||
 | 
								result += "'";
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '&':
 | 
				
			||||||
 | 
								result += "&";
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			result += c;
 | 
								result += c;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -93,7 +99,7 @@ std::vector<std::string> utils::split(const std::string &str, char delim)
 | 
				
			|||||||
// TODO: can easily break if we pass a regex here
 | 
					// TODO: can easily break if we pass a regex here
 | 
				
			||||||
std::vector<std::string> utils::split(const std::string &str, const std::string &delim)
 | 
					std::vector<std::string> utils::split(const std::string &str, const std::string &delim)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::regex regex { delim + "+" };
 | 
						std::regex regex{delim + "+"};
 | 
				
			||||||
	return split(str, regex);
 | 
						return split(str, regex);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Viittaa uudesa ongelmassa
	
	Block a user