Skip to content

Commit 2872b95

Browse files
Fix three errors
Sandbox level 3 would prevent most GPU drivers from loading because it prevented write accesst to /dev. Xorg connection failed when no display is present, now falls back to 'none' WSI when this happens. --presentation cmd line parameter was typo'ed during parsing.
1 parent 5b37f99 commit 2872b95

File tree

5 files changed

+49
-75
lines changed

5 files changed

+49
-75
lines changed

src/replay.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,7 @@ static void replay_thread(int thread_id)
116116

117117
static void run_multithreaded()
118118
{
119-
if (p__sandbox_level >= 3)
120-
{
121-
const char* err = sandbox_level_three();
122-
if (err) WLOG("Warning: Failed to increase sandbox to level three: %s", err);
123-
}
119+
if (p__sandbox_level >= 3) sandbox_level_three();
124120

125121
for (unsigned i = 0; i < replayer.threads.size(); i++)
126122
{
@@ -143,11 +139,7 @@ int main(int argc, char **argv)
143139
bool infodump = false;
144140
std::string wsi;
145141

146-
if (p__sandbox_level >= 1)
147-
{
148-
const char* err = sandbox_level_one();
149-
if (err) WLOG("Warning: Failed to increase sandbox to level one: %s", err);
150-
}
142+
if (p__sandbox_level >= 1) sandbox_level_one();
151143

152144
// override defaults
153145
//p__allow_stalls = get_env_bool("LAVATUBE_ALLOW_STALLS", false);
@@ -186,7 +178,7 @@ int main(int argc, char **argv)
186178
else if (val == "offscreen") p__noscreen = 1;
187179
else ABORT("Bad --swapchain mode");
188180
}
189-
else if (match(argv[i], nullptr, "--presentationmode", remaining))
181+
else if (match(argv[i], nullptr, "--presentation", remaining))
190182
{
191183
if (remaining < 1) usage();
192184
std::string val = get_str(argv[++i], remaining);
@@ -306,11 +298,7 @@ int main(int argc, char **argv)
306298
if (wsi.empty()) wsi_initialize(nullptr);
307299
else wsi_initialize(wsi.c_str());
308300

309-
if (p__sandbox_level >= 2)
310-
{
311-
const char* err = sandbox_level_two();
312-
if (err) WLOG("Warning: Failed to increase sandbox to level two: %s", err);
313-
}
301+
if (p__sandbox_level >= 2) sandbox_level_two();
314302

315303
if (filename.empty())
316304
{

src/sandbox.cpp

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <stdbool.h>
2424

2525
#include "sandbox.h"
26+
#include "util.h"
2627

2728
#ifndef landlock_create_ruleset
2829
static inline int
@@ -51,20 +52,19 @@ static inline int landlock_restrict_self(const int ruleset_fd,
5152
}
5253
#endif
5354

54-
const char* sandbox_level_one()
55+
void sandbox_level_one()
5556
{
56-
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) { return "Failed to restrict root privileges"; }
57-
return nullptr;
57+
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) ABORT("Failed to restrict root privileges");
5858
}
5959

60-
const char* sandbox_level_two()
60+
void sandbox_level_two()
6161
{
6262
int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
6363
if (abi < 0)
6464
{
65-
if (errno == ENOSYS) return "Landlock sandbox is not supported by the current kernel";
66-
else if (errno == EOPNOTSUPP) return "Landlock sandbox is currently disabled";
67-
else return "Landlock sandboxing not supported by your system for unknown reason";
65+
if (errno == ENOSYS) ABORT("Landlock sandbox is not supported by the current kernel");
66+
else if (errno == EOPNOTSUPP) ABORT("Landlock sandbox is currently disabled");
67+
else ABORT("Landlock sandboxing not supported by your system: %s", strerror(errno));
6868
}
6969
struct landlock_ruleset_attr ruleset_attr = {};
7070
// Prohibit things we never need to do:
@@ -73,43 +73,37 @@ const char* sandbox_level_two()
7373
ruleset_attr.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP;
7474
#endif
7575
int ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
76-
if (ruleset_fd < 0) return "Failed to create landlock ruleset";
77-
if (landlock_restrict_self(ruleset_fd, 0)) { close(ruleset_fd); return "Failed to enforce landlock ruleset"; }
76+
if (ruleset_fd < 0) ABORT("Failed to create landlock ruleset: %s", strerror(errno));
77+
if (landlock_restrict_self(ruleset_fd, 0) != 0) ABORT("Failed to enforce landlock ruleset: %s", strerror(errno));
7878
close(ruleset_fd);
79+
}
7980

80-
return nullptr;
81+
static void sandbox_except_path(int ruleset_fd, const char* path, int access_flags)
82+
{
83+
struct landlock_path_beneath_attr path_beneath = {};
84+
path_beneath.allowed_access = access_flags;
85+
path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
86+
if (path_beneath.parent_fd < 0) ABORT("Failed to add exception for an app path from sandbox restrictions: %s", strerror(errno));
87+
if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0) != 0) ABORT("Failed to add path exception to landlock sandbox ruleset: %s", strerror(errno));
88+
close(path_beneath.parent_fd);
8189
}
8290

83-
const char* sandbox_level_three()
91+
void sandbox_level_three()
8492
{
85-
char path[255];
86-
memset(path, 0, sizeof(path));
87-
const char* exception_path = getcwd(path, sizeof(path));
88-
// Error would have been spammed during init, do not need to repeat it; if we got here, we decided to ignore it
89-
if (landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION) < 0) return nullptr;
9093
// Prohibit things we don't need during replay
9194
struct landlock_ruleset_attr ruleset_attr = {};
9295
ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE;
9396
int ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
94-
if (ruleset_fd < 0) return "Failed to create landlock ruleset";
97+
if (ruleset_fd < 0) ABORT("Failed to create landlock ruleset: %s", strerror(errno));
98+
9599
// Set up exception path from current working directory
96-
if (exception_path)
97-
{
98-
struct landlock_path_beneath_attr path_beneath = {};
99-
path_beneath.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_REMOVE_DIR;
100-
path_beneath.parent_fd = open(exception_path, O_PATH | O_CLOEXEC);
101-
if (path_beneath.parent_fd < 0) { close(ruleset_fd); return "Failed to open app path"; }
102-
int err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0);
103-
if (err)
104-
{
105-
printf("1: %s\n", strerror(errno));
106-
close(ruleset_fd);
107-
close(path_beneath.parent_fd);
108-
return "Failed to add path exception to landlock sandbox ruleset";
109-
}
110-
close(path_beneath.parent_fd);
111-
}
112-
if (landlock_restrict_self(ruleset_fd, 0)) { close(ruleset_fd); return "Failed to enforce landlock ruleset"; }
100+
char path[255];
101+
memset(path, 0, sizeof(path));
102+
const char* exception_path = getcwd(path, sizeof(path));
103+
sandbox_except_path(ruleset_fd, exception_path, LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_REMOVE_DIR);
104+
sandbox_except_path(ruleset_fd, "/dev", LANDLOCK_ACCESS_FS_WRITE_FILE);
105+
106+
if (landlock_restrict_self(ruleset_fd, 0) != 0) ABORT("Failed to enforce landlock ruleset: %s", strerror(errno));
107+
113108
close(ruleset_fd);
114-
return nullptr;
115109
}

src/sandbox.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
#pragma once
22

33
/// Basic sandboxing that you always want. Call this immediately upon program start.
4-
const char* sandbox_level_one();
4+
void sandbox_level_one();
55

66
/// Run at the program start after evaluating command-line arguments. It will limit certain policies that we never need.
7-
/// Returns null on success, or an error string on failure. Initialize the window system integration before calling this.
8-
const char* sandbox_level_two();
7+
/// Initialize the window system integration before calling this.
8+
void sandbox_level_two();
99

10-
/// You need to open all files prior to starting this, eg if you want to dump results into a JSON, open the output file first.
11-
/// Returns null on success, or an error string on failure. Note that this applies to an individual thread and its children,
12-
/// so use before spawning or apply to it to each child and the parent thread, and make sure child threads cannot race the
13-
/// parent setting its policy.
14-
const char* sandbox_level_three();
10+
/// Run right before starting parsing untrusted data, after setting up all internal state and connections.
11+
void sandbox_level_three();

src/tool.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ static std::string get_str(const char* in, int& remaining)
7373

7474
static void replay_thread(lava_reader* replayer, int thread_id)
7575
{
76-
if (p__sandbox_level >= 2)
77-
{
78-
const char* err = sandbox_level_three();
79-
if (err) WLOG("Warning: Failed to increase sandbox to level three: %s", err);
80-
}
76+
if (p__sandbox_level >= 2) sandbox_level_three();
8177
lava_file_reader& t = replayer->file_reader(thread_id);
8278
uint8_t instrtype;
8379
assert(t.run == false);
@@ -163,11 +159,7 @@ int main(int argc, char **argv)
163159
std::string filename_output;
164160
bool validate_remap = false;
165161

166-
if (p__sandbox_level >= 1)
167-
{
168-
const char* err = sandbox_level_one();
169-
if (err) WLOG("Warning: Failed to increase sandbox to level one: %s", err);
170-
}
162+
if (p__sandbox_level >= 1) sandbox_level_one();
171163

172164
for (int i = 1; i < argc; i++)
173165
{
@@ -248,11 +240,7 @@ int main(int argc, char **argv)
248240

249241
if (!filename_output.empty()) DIE("Output file support still to be done!");
250242

251-
if (p__sandbox_level >= 3)
252-
{
253-
const char* err = sandbox_level_two();
254-
if (err) WLOG("Warning: Failed to increase sandbox to level two: %s", err);
255-
}
243+
if (p__sandbox_level >= 3) sandbox_level_two();
256244

257245
std::list<address_rewrite> rewrite_queue_copy;
258246

src/window.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,17 @@ void wsi_initialize(const char* name)
119119
int scr = 0;
120120
context.xcb.connection = xcb_connect(nullptr, &scr);
121121
int err = xcb_connection_has_error(context.xcb.connection);
122-
if (err)
122+
if (err && name)
123123
{
124124
ABORT("Failed to connect to XCB server: %s (%d)", lavaxcb_strerror(err), err);
125125
}
126+
else if (err) // graceful fallback
127+
{
128+
ILOG("Failed to connect to XCB server (%s) -- falling back to \"none\" WSI ", lavaxcb_strerror(err));
129+
context.winsys = "none";
130+
p__noscreen = 1;
131+
return;
132+
}
126133
const xcb_setup_t *setup = xcb_get_setup(context.xcb.connection);
127134
if (!setup) ABORT("Failed to setup XCB connection");
128135
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);

0 commit comments

Comments
 (0)