From 2ac589448f212b9b17cbed87c740fec98458283f Mon Sep 17 00:00:00 2001 From: Mathew Gordon Date: Mon, 1 Jul 2024 05:20:34 -0600 Subject: [PATCH] Work on aisap-zig sockets My current plan is to no longer hard code permissions flags. Instead, they will all be defined in JSON, which will be easier to maintain and hopefully allow others to more easily utilize aisap in other projects --- permissions/sockets.json | 161 --------- zig/build.zig.zon | 6 +- zig/examples/build.zig | 2 +- zig/examples/src/main.zig | 15 +- zig/lib/appimage.zig | 703 +++++++++++++++++++------------------- zig/sockets.json | 64 ++++ 6 files changed, 420 insertions(+), 531 deletions(-) delete mode 100644 permissions/sockets.json create mode 100644 zig/sockets.json diff --git a/permissions/sockets.json b/permissions/sockets.json deleted file mode 100644 index 7b1a795..0000000 --- a/permissions/sockets.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "alsa": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/usr/share/alsa", - "dest": "/usr/share/alsa" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/alsa", - "dest": "/etc/alsa" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/group", - "dest": "/etc/group" - }, - { - "flag": "--dev-bind", - "resolve_symlink": true, - "src": "/dev/snd", - "dest": "/dev/snd" - } - ], - "cgroup": [], - "dbus": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "$XDG_RUNTIME_DIR/bus", - "dest": "/run/user/$UID/bus" - } - ], - "ipc": [], - "network": [ - { - "flag": "--share-net" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/ca-certificates", - "dest": "/etc/ca-certificates" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/resolv.conf", - "dest": "/etc/resolv.conf" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/ssl", - "dest": "/etc/ssl" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/pki", - "dest": "/etc/pki" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/usr/share/ca-certificates", - "dest": "/usr/share/ca-certificates" - } - ], - "pid": [], - "pipewire": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "$XDG_RUNTIME_DIR/pipewire-0", - "dest": "/run/user/$UID/pipewire-0" - } - ], - "pulseaudio": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "$XDG_RUNTIME_DIR/pulse", - "dest": "/run/user/$UID/pulse" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/etc/pulse", - "dest": "/etc/pulse" - } - ], - "session": [], - "user": [], - "uts": [], - "wayland": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY", - "dest": "/run/user/$UID/wayland-0" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/usr/share/X11", - "dest": "/usr/share/X11" - }, - { - "flag": "--setenv", - "src": "WAYLAND_DISPLAY", - "dest": "wayland-0" - }, - { - "flag": "--setenv", - "src": "_JAVA_AWT_WM_NONPARENTING", - "dest": "1" - }, - { - "flag": "--setenv", - "src": "MOZ_ENABLE_WAYLAND", - "dest": "1" - }, - { - "flag": "--setenv", - "src": "XDG_SESSION_TYPE", - "dest": "wayland" - } - ], - "x11": [ - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "$XAUTHORITY", - "dest": "$HOME/.Xauthority" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - - "_COMMENT_": "TODO: represent display correctly", - "src": "$TMPDIR/.X11-unix/X$DISPLAY", - - "dest": "/usr/share/X11" - }, - { - "flag": "--ro-bind-try", - "resolve_symlink": true, - "src": "/usr/share/X11", - "dest": "/usr/share/X11" - }, - { - "flag": "--setenv", - "src": "XAUTHORITY", - "dest": "$HOME/.Xauthority" - } - ] -} diff --git a/zig/build.zig.zon b/zig/build.zig.zon index b342ad1..fbc1d84 100644 --- a/zig/build.zig.zon +++ b/zig/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = "aisap", - .version = "0.10.11-alpha", + .version = "0.10.1-alpha", .paths = [][]const u8 {""}, .dependencies = .{ .squashfuse = .{ @@ -12,8 +12,8 @@ .hash = "12205592f7dc4b4c7256abd657a50bd9784459a0e9b8bfe8b0d1bbcc153a6d0f650a", }, .known_folders = .{ - .url = "https://github.com/ziglibs/known-folders/archive/0ad514dcfb7525e32ae349b9acc0a53976f3a9fa.tar.gz", - .hash = "12209cde192558f8b3dc098ac2330fc2a14fdd211c5433afd33085af75caa9183147", + .url = "https://github.com/ziglibs/known-folders/archive/cdcc6137ed2e92096b27d394db917d1861f156b3.tar.gz", + .hash = "1220863f0fc3e97cfd47a8edb28c7a3d109c42143235042fb513207b5c5a032fb93f", }, }, } diff --git a/zig/examples/build.zig b/zig/examples/build.zig index 2b3cd81..9c88b19 100644 --- a/zig/examples/build.zig +++ b/zig/examples/build.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const aisap = @import("aisap/zig/build.zig"); +//const aisap = @import("aisap/zig/build.zig"); pub fn build(b: *std.Build) void { // Standard target options allows the person running `zig build` to choose diff --git a/zig/examples/src/main.zig b/zig/examples/src/main.zig index 60bdece..3cdad1b 100644 --- a/zig/examples/src/main.zig +++ b/zig/examples/src/main.zig @@ -62,7 +62,7 @@ pub fn main() !void { var md5_buf: [33]u8 = undefined; - const permissions = try ai.permissions( + var permissions = try ai.permissions( allocator, ) orelse { std.debug.print("no permissions found\n", .{}); @@ -85,6 +85,9 @@ pub fn main() !void { std.debug.print("[]\n", .{}); } + permissions.level = 3; + try AppImage.SocketPermissions.initDatabase(allocator); + std.debug.print("{s}\n", .{ai.name}); std.debug.print("desktop: {s}\n", .{ai.desktop_entry}); std.debug.print("type: {}\n", .{ai.kind}); @@ -93,12 +96,14 @@ pub fn main() !void { try ai.md5(&md5_buf), }); - try ai.mount(.{}); + try ai.mount(.{ + .foreground = false, + }); - const wrapArgs = try ai.wrapArgs(allocator); - printWrapArgs(wrapArgs); + //const wrapArgs = try ai.wrapArgs(allocator, permissions); + //printWrapArgs(wrapArgs); - try ai.sandbox(.{ + try ai.sandbox(permissions, .{ //.args = &[_][]const u8{"build"}, }); } diff --git a/zig/lib/appimage.zig b/zig/lib/appimage.zig index afa1b16..da4aae1 100644 --- a/zig/lib/appimage.zig +++ b/zig/lib/appimage.zig @@ -381,7 +381,6 @@ pub const AppImage = struct { pub const SocketPermissions = enum { alsa, - audio, cgroup, dbus, ipc, @@ -395,6 +394,30 @@ pub const AppImage = struct { wayland, x11, + const JsonSocket = struct { + name: []const u8, + flags: ?[]const []const u8 = null, + }; + + // Parses the built-in JSON database into a HashMap + // TODO: do this comptime + pub fn initDatabase(allocator: std.mem.Allocator) !void { + const sockets_json = @embedFile("../sockets.json"); + + const parsed = try std.json.parseFromSlice( + []JsonSocket, + allocator, + sockets_json, + .{}, + ); + defer parsed.deinit(); + + for (parsed.value) |val| { + std.debug.print("name: {s}\n", .{val.name}); + std.debug.print("flags: {?s}\n", .{val.flags}); + } + } + pub fn fromString(sock: []const u8) !SocketPermissions { return std.meta.stringToEnum( SocketPermissions, @@ -419,6 +442,14 @@ pub const AppImage = struct { ); } + // pub fn toBwrapArgs(allocator: std.mem.Allocator, opts: SocketOptions,) ![]const []const u8 { + // _ = opts; + // + // var list = std.ArrayList([]const u8).init(allocator); + // + // + // } + /// Generates bwrap args from socket. Memory is cleared on each call /// to the method pub fn toBwrapArgs( @@ -440,37 +471,6 @@ pub const AppImage = struct { "--ro-bind-try", "/etc/group", "/etc/group", "--dev-bind", "/dev/snd", "/dev/snd", }, - .audio => blk: { - const runtime_pulse_dir = try std.fmt.allocPrint( - allocator, - "{s}/pulse", - .{opts.runtime_dir}, - ); - defer allocator.free(runtime_pulse_dir); - - const dest_pulse_dir = try std.fmt.allocPrint( - allocator, - "/run/user/{d}/pulse", - .{opts.uid}, - ); - defer allocator.free(dest_pulse_dir); - - var list = std.ArrayList([]const u8).init(allocator); - - try list.appendSlice( - &[_][]const u8{ - "--ro-bind-try", runtime_pulse_dir, dest_pulse_dir, - "--ro-bind-try", "/usr/share/alsa", "/usr/share/alsa", - "--ro-bind-try", "/usr/share/pulseaudio", "/usr/share/pulseaudio", - "--ro-bind-try", "/etc/alsa", "/etc/alsa", - "--ro-bind-try", "/etc/group", "/etc/group", - "--ro-bind-try", "/etc/pulse", "/etc/pulse", - "--dev-bind", "/dev/snd", "/dev/snd", - }, - ); - - break :blk try list.toOwnedSlice(); - }, .cgroup => &[_][]const u8{}, .dbus => blk: { const runtime_bus_dir = try appendDir( @@ -689,17 +689,16 @@ pub const AppImage = struct { // TODO: finish implementing in Zig // TODO: free allocated memory. Currently, this should just be allocated using an arena - pub fn wrapArgs(ai: *AppImage, allocator: std.mem.Allocator) ![]const []const u8 { + pub fn wrapArgs( + ai: *AppImage, + allocator: std.mem.Allocator, + perms: Permissions, + ) ![]const []const u8 { if (ai.mount_dir == null) { return WrapArgsError.BundleNotMounted; } - var perms = try ai.permissions(allocator) orelse { - return WrapArgsError.NoPermissions; - }; - defer perms.deinit(); - - //if (perms.level == 0) return WrapArgsError.SandboxLevelTooLow; + if (perms.level == 0) return WrapArgsError.SandboxLevelTooLow; const home = try known_folders.getPath(allocator, .home) orelse { return WrapArgsError.HomeNotFound; @@ -708,361 +707,359 @@ pub const AppImage = struct { var list = std.ArrayList([]const u8).init(allocator); try list.append("bwrap"); - if (perms.level > 0) { - var md5_buf: [33]u8 = undefined; - const ai_md5 = try ai.md5(&md5_buf); + var md5_buf: [33]u8 = undefined; + const ai_md5 = try ai.md5(&md5_buf); + + // TODO: fallback if `LOGNAME` not present + const logname = std.posix.getenv("LOGNAME") orelse ""; + const user = try std.process.getUserInfo(logname); + + // Bwrap args for AppImages regardless of level + try list.appendSlice(&[_][]const u8{ + "--setenv", "TMPDIR", "/tmp", + "--setenv", "HOME", home, + "--setenv", "ARGV0", fs.path.basename(ai.path), + + // If these directories are symlinks, they will be resolved, + // otherwise + "--ro-bind-try", try resolve(allocator, "/opt"), "/opt", + "--ro-bind-try", try resolve(allocator, "/bin"), "/bin", + "--ro-bind-try", try resolve(allocator, "/sbin"), "/sbin", + "--ro-bind-try", try resolve(allocator, "/lib"), "/lib", + "--ro-bind-try", try resolve(allocator, "/lib32"), "/lib32", + "--ro-bind-try", try resolve(allocator, "/lib64"), "/lib64", + "--ro-bind-try", try resolve(allocator, "/usr/bin"), "/usr/bin", + "--ro-bind-try", try resolve(allocator, "/usr/sbin"), "/usr/sbin", + "--ro-bind-try", try resolve(allocator, "/usr/lib"), "/usr/lib", + "--ro-bind-try", try resolve(allocator, "/usr/lib32"), "/usr/lib32", + "--ro-bind-try", try resolve(allocator, "/usr/lib64"), "/usr/lib64", + + "--setenv", "APPDIR", + try std.fmt.allocPrint( + allocator, + "/tmp/.mount_{s}", + .{ai_md5}, + ), - // TODO: fallback if `LOGNAME` not present - const logname = std.posix.getenv("LOGNAME") orelse ""; - const user = try std.process.getUserInfo(logname); + "--setenv", "APPIMAGE", + try std.fmt.allocPrint( + allocator, + "/app/{s}", + .{fs.path.basename(ai.path)}, + ), - // Bwrap args for AppImages regardless of level - try list.appendSlice(&[_][]const u8{ - "--setenv", "TMPDIR", "/tmp", - "--setenv", "HOME", home, - "--setenv", "ARGV0", fs.path.basename(ai.path), - - // If these directories are symlinks, they will be resolved, - // otherwise - "--ro-bind-try", try resolve(allocator, "/opt"), "/opt", - "--ro-bind-try", try resolve(allocator, "/bin"), "/bin", - "--ro-bind-try", try resolve(allocator, "/sbin"), "/sbin", - "--ro-bind-try", try resolve(allocator, "/lib"), "/lib", - "--ro-bind-try", try resolve(allocator, "/lib32"), "/lib32", - "--ro-bind-try", try resolve(allocator, "/lib64"), "/lib64", - "--ro-bind-try", try resolve(allocator, "/usr/bin"), "/usr/bin", - "--ro-bind-try", try resolve(allocator, "/usr/sbin"), "/usr/sbin", - "--ro-bind-try", try resolve(allocator, "/usr/lib"), "/usr/lib", - "--ro-bind-try", try resolve(allocator, "/usr/lib32"), "/usr/lib32", - "--ro-bind-try", try resolve(allocator, "/usr/lib64"), "/usr/lib64", - - "--setenv", "APPDIR", + // Set generic paths for all XDG standard dirs + "--setenv", "XDG_DESKTOP_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Desktop", + .{home}, + ), + "--setenv", "XDG_DOWNLOAD_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Downloads", + .{home}, + ), + "--setenv", "XDG_DOCUMENTS_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Documents", + .{home}, + ), + "--setenv", "XDG_MUSIC_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Music", + .{home}, + ), + "--setenv", "XDG_PICTURES_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Pictures", + .{home}, + ), + "--setenv", "XDG_VIDEOS_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Videos", + .{home}, + ), + "--setenv", "XDG_TEMPLATES_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Templates", + .{home}, + ), + "--setenv", "XDG_PUBLICSHARE_DIR", + try std.fmt.allocPrint( + allocator, + "{s}/Share", + .{home}, + ), + "--setenv", "XDG_DATA_HOME", + try std.fmt.allocPrint( + allocator, + "{s}/.local/share", + .{home}, + ), + "--setenv", "XDG_CONFIG_HOME", + try std.fmt.allocPrint( + allocator, + "{s}/.config", + .{home}, + ), + "--setenv", "XDG_CACHE_HOME", + try std.fmt.allocPrint( + allocator, + "{s}/.cache", + .{home}, + ), + "--setenv", "XDG_STATE_HOME", + try std.fmt.allocPrint( + allocator, + "{s}/.local/state", + .{home}, + ), + "--setenv", "XDG_RUNTIME_DIR", + try std.fmt.allocPrint( + allocator, + "/run/user/{d}", + .{user.uid}, + ), + "--perms", "0700", // + "--dir", + try std.fmt.allocPrint( + allocator, + "/run/user/{d}", + .{user.uid}, + ), + "--dev", "/dev", + "--proc", "/proc", + "--dir", "/app", + + "--bind", ai.path, + try std.fmt.allocPrint( + allocator, + "/app/{s}", + .{fs.path.basename(ai.path)}, + ), + + // TODO: fallback if no cache + "--bind-try", + try std.fmt.allocPrint( + allocator, + "{s}/appimage/{s}", + .{ + (try known_folders.getPath(allocator, .cache)).?, + ai_md5, + }, + ), + try std.fmt.allocPrint( + allocator, + "{s}/.cache", + .{home}, + ), + + "--die-with-parent", + }); + + const config = (try known_folders.getPath(allocator, .local_configuration)).?; + + // Per-level arguments + try list.appendSlice(switch (perms.level) { + 0 => unreachable, + 1 => &[_][]const u8{ + "--dev-bind", "/dev", "/dev", + "--ro-bind", "/sys", "/sys", + "--ro-bind-try", "/usr", "/usr", + "--ro-bind-try", "/etc", "/etc", + "--ro-bind-try", "/run/systemd", "/run/systemd", + // TODO: do this a better way + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "/tmp/.mount_{s}", - .{ai_md5}, + "{s}/.fonts", + .{home}, ), - - "--setenv", "APPIMAGE", try std.fmt.allocPrint( allocator, - "/app/{s}", - .{fs.path.basename(ai.path)}, + "{s}/.fonts", + .{home}, ), - - // Set generic paths for all XDG standard dirs - "--setenv", "XDG_DESKTOP_DIR", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/Desktop", - .{home}, + "{s}/fontconfig", + .{config}, ), - "--setenv", "XDG_DOWNLOAD_DIR", try std.fmt.allocPrint( allocator, - "{s}/Downloads", - .{home}, + "{s}/fontconfig", + .{config}, ), - "--setenv", "XDG_DOCUMENTS_DIR", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/Documents", - .{home}, + "{s}/gtk-3.0", + .{config}, ), - "--setenv", "XDG_MUSIC_DIR", try std.fmt.allocPrint( allocator, - "{s}/Music", - .{home}, + "{s}/gtk-3.0", + .{config}, ), - "--setenv", "XDG_PICTURES_DIR", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/Pictures", - .{home}, + "{s}/kdeglobals", + .{config}, ), - "--setenv", "XDG_VIDEOS_DIR", try std.fmt.allocPrint( allocator, - "{s}/Videos", - .{home}, + "{s}/kdeglobals", + .{config}, ), - "--setenv", "XDG_TEMPLATES_DIR", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/Templates", - .{home}, + "{s}/lxde/lxde.conf", + .{config}, ), - "--setenv", "XDG_PUBLICSHARE_DIR", try std.fmt.allocPrint( allocator, - "{s}/Share", - .{home}, + "{s}/lxde/lxde.conf", + .{config}, ), - "--setenv", "XDG_DATA_HOME", + }, + 2 => &[_][]const u8{ + "--ro-bind-try", "/etc/fonts", "/etc/fonts", + "--ro-bind-try", "/etc/ld.so.cache", "/etc/ld.so.cache", + "--ro-bind-try", "/etc/mime.types", "/etc/mime.types", + "--ro-bind-try", "/usr/share/fontconfig", "/usr/share/fontconfig", + "--ro-bind-try", "/usr/share/fonts", "/usr/share/fonts", + "--ro-bind-try", "/usr/share/icons", "/usr/share/icons", + "--ro-bind-try", "/usr/share/applications", "/usr/share/applications", + "--ro-bind-try", "/usr/share/mime", "/usr/share/mime", + "--ro-bind-try", "/usr/share/libdrm", "/usr/share/libdrm", + "--ro-bind-try", "/usr/share/glvnd", "/usr/share/glvnd", + "--ro-bind-try", "/usr/share/glib-2.0", "/usr/share/glib-2.0", + "--ro-bind-try", "/usr/share/terminfo", "/usr/share/terminfo", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/.local/share", + "{s}/.fonts", .{home}, ), - "--setenv", "XDG_CONFIG_HOME", try std.fmt.allocPrint( allocator, - "{s}/.config", + "{s}/.fonts", .{home}, ), - "--setenv", "XDG_CACHE_HOME", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/.cache", - .{home}, + "{s}/fontconfig", + .{config}, ), - "--setenv", "XDG_STATE_HOME", try std.fmt.allocPrint( allocator, - "{s}/.local/state", - .{home}, + "{s}/fontconfig", + .{config}, ), - "--setenv", "XDG_RUNTIME_DIR", + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "/run/user/{d}", - .{user.uid}, + "{s}/gtk-3.0", + .{config}, ), - "--perms", "0700", // - "--dir", try std.fmt.allocPrint( allocator, - "/run/user/{d}", - .{user.uid}, + "{s}/gtk-3.0", + .{config}, ), - "--dev", "/dev", - "--proc", "/proc", - "--dir", "/app", - - "--bind", ai.path, + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "/app/{s}", - .{fs.path.basename(ai.path)}, + "{s}/kdeglobals", + .{config}, ), - - // TODO: fallback if no cache - "--bind-try", try std.fmt.allocPrint( allocator, - "{s}/appimage/{s}", - .{ - (try known_folders.getPath(allocator, .cache)).?, - ai_md5, - }, + "{s}/kdeglobals", + .{config}, ), + "--ro-bind-try", try std.fmt.allocPrint( allocator, - "{s}/.cache", - .{home}, + "{s}/lxde/lxde.conf", + .{config}, ), + try std.fmt.allocPrint( + allocator, + "{s}/lxde/lxde.conf", + .{config}, + ), + }, + 3 => &[_][]const u8{}, + }); - "--die-with-parent", - }); - - const config = (try known_folders.getPath(allocator, .local_configuration)).?; - - // Per-level arguments - try list.appendSlice(switch (perms.level) { - 0 => unreachable, - 1 => &[_][]const u8{ - "--dev-bind", "/dev", "/dev", - "--ro-bind", "/sys", "/sys", - "--ro-bind-try", "/usr", "/usr", - "--ro-bind-try", "/etc", "/etc", - "--ro-bind-try", "/run/systemd", "/run/systemd", - // TODO: do this a better way - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/.fonts", - .{home}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/.fonts", - .{home}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/fontconfig", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/fontconfig", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/gtk-3.0", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/gtk-3.0", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/kdeglobals", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/kdeglobals", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/lxde/lxde.conf", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/lxde/lxde.conf", - .{config}, - ), - }, - 2 => &[_][]const u8{ - "--ro-bind-try", "/etc/fonts", "/etc/fonts", - "--ro-bind-try", "/etc/ld.so.cache", "/etc/ld.so.cache", - "--ro-bind-try", "/etc/mime.types", "/etc/mime.types", - "--ro-bind-try", "/usr/share/fontconfig", "/usr/share/fontconfig", - "--ro-bind-try", "/usr/share/fonts", "/usr/share/fonts", - "--ro-bind-try", "/usr/share/icons", "/usr/share/icons", - "--ro-bind-try", "/usr/share/applications", "/usr/share/applications", - "--ro-bind-try", "/usr/share/mime", "/usr/share/mime", - "--ro-bind-try", "/usr/share/libdrm", "/usr/share/libdrm", - "--ro-bind-try", "/usr/share/glvnd", "/usr/share/glvnd", - "--ro-bind-try", "/usr/share/glib-2.0", "/usr/share/glib-2.0", - "--ro-bind-try", "/usr/share/terminfo", "/usr/share/terminfo", - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/.fonts", - .{home}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/.fonts", - .{home}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/fontconfig", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/fontconfig", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/gtk-3.0", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/gtk-3.0", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/kdeglobals", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/kdeglobals", - .{config}, - ), - "--ro-bind-try", - try std.fmt.allocPrint( - allocator, - "{s}/lxde/lxde.conf", - .{config}, - ), - try std.fmt.allocPrint( - allocator, - "{s}/lxde/lxde.conf", - .{config}, - ), - }, - 3 => &[_][]const u8{}, + if (perms.data_dir) { + // try list.appendSlice( + // "--bind", + // ai. + // ); + } else { + try list.appendSlice(&[_][]const u8{ + "--tmpfs", + home, }); + } - if (perms.data_dir) { - // try list.appendSlice( - // "--bind", - // ai. - // ); - } else { - try list.appendSlice(&[_][]const u8{ - "--tmpfs", - home, - }); - } - - if (perms.filesystem) |files| { - for (files) |*file| { - try list.appendSlice( - try file.toBwrapArgs(allocator), - ); - } - } - - if (perms.sockets) |sockets| { - for (sockets) |socket| { - const socket_slice = try socket.toBwrapArgs(allocator, .{ - // TODO: DO NOT HARD CODE - .runtime_dir = "/run/user/1000", - .uid = 1000, - }); - defer allocator.free(socket_slice); - - try list.appendSlice(socket_slice); - } + if (perms.filesystem) |files| { + for (files) |*file| { + try list.appendSlice( + try file.toBwrapArgs(allocator), + ); } + } - if (ai.mount_dir) |mount_dir| { - try list.appendSlice(&[_][]const u8{ - "--bind", - mount_dir, - try std.fmt.allocPrint( - allocator, - "/tmp/.mount_{s}", - .{ - ai_md5, - }, - ), + if (perms.sockets) |sockets| { + for (sockets) |socket| { + const socket_slice = try socket.toBwrapArgs(allocator, .{ + // TODO: DO NOT HARD CODE + .runtime_dir = "/run/user/1000", + .uid = 1000, }); + defer allocator.free(socket_slice); + + try list.appendSlice(socket_slice); } + } + if (ai.mount_dir) |mount_dir| { try list.appendSlice(&[_][]const u8{ - "--", + "--bind", + mount_dir, try std.fmt.allocPrint( allocator, - "/tmp/.mount_{s}/AppRun", - .{ai_md5}, + "/tmp/.mount_{s}", + .{ + ai_md5, + }, ), }); } + try list.appendSlice(&[_][]const u8{ + "--", + try std.fmt.allocPrint( + allocator, + "/tmp/.mount_{s}/AppRun", + .{ai_md5}, + ), + }); + return list.toOwnedSlice(); } @@ -1136,43 +1133,32 @@ pub const AppImage = struct { const off = try ai.offset(); if (opts.foreground) { - try fuse_helper.mountImage(ai.path, ai.mount_dir.?, off); + @panic("not yet implemented"); + //try fuse_helper.mountImage(ai.path, ai.mount_dir.?, off); } else { - const pid = try posix.fork(); - if (pid == 0) { - // _ = try std.Thread.spawn( - // .{}, - // fuse_helper.mountImage, - // .{ ai.path, ai.mount_dir.?, off }, - // ); - - if (true) { - try fuse_helper.mountImage( - ai.path, - ai.mount_dir.?, - off, - ); - } else { - const offset_string = try std.fmt.allocPrint( - ai.allocator, - "-ooffset={d}", - .{off}, - ); - defer ai.allocator.free(offset_string); - - var proc = std.process.Child.init(&[_][]const u8{ - "squashfuse", - offset_string, - ai.path, - ai.mount_dir.?, - }, ai.allocator); - - _ = try proc.spawnAndWait(); - } - - std.debug.print("UNMOUNT\n\n", .{}); - - posix.exit(0); + // TODO: fix squashfuse-zig crash here + if (false) { + try fuse_helper.mountImage( + ai.path, + ai.mount_dir.?, + off, + ); + } else { + const offset_string = try std.fmt.allocPrint( + ai.allocator, + "-ooffset={d}", + .{off}, + ); + defer ai.allocator.free(offset_string); + + var proc = std.process.Child.init(&[_][]const u8{ + "squashfuse", + offset_string, + ai.path, + ai.mount_dir.?, + }, ai.allocator); + + _ = try proc.spawnAndWait(); } // Values in nanoseconds @@ -1238,17 +1224,12 @@ pub const AppImage = struct { }; // This can't be finished until AppImage.wrapArgs works correctly - pub fn sandbox(ai: *AppImage, opts: SandboxOptions) !void { + pub fn sandbox(ai: *AppImage, perms: Permissions, opts: SandboxOptions) !void { var arena = std.heap.ArenaAllocator.init(ai.allocator); const arena_allocator = arena.allocator(); defer arena.deinit(); - const wrap_args = try ai.wrapArgs(arena_allocator); - - std.debug.print("DEBUG {s} {s}", .{ - @src().fn_name, - wrap_args, - }); + const wrap_args = try ai.wrapArgs(arena_allocator, perms); if (opts.args) |args| { var list = std.ArrayList([]const u8).init(arena_allocator); diff --git a/zig/sockets.json b/zig/sockets.json new file mode 100644 index 0000000..93e3718 --- /dev/null +++ b/zig/sockets.json @@ -0,0 +1,64 @@ +[ + { + "name": "alsa", + "flags": [ + "--ro-bind-try", "/usr/share/alsa", "/usr/share/alsa" + ] + }, + { "name": "cgroup" }, + { + "name": "dbus", + "flags": [ + "--ro-bind-try", "$XDG_RUNTIME_DIR/bus", "/run/user/$UID/bus" + ] + }, + { "name": "ipc" }, + { + "name": "network", + "flags": [ + "--share-net", + "--ro-bind-try", "/etc/ca-certificates", "/etc/ca-certificates", + "--ro-bind-try", "/etc/resolv.conf", "/etc/resolv.conf", + "--ro-bind-try", "/etc/ssl", "/etc/ssl", + "--ro-bind-try", "/etc/pki", "/etc/pki", + "--ro-bind-try", "/usr/share/ca-certificates", "/usr/share/ca-certificates" + ] + }, + { "name": "pid" }, + { + "name": "pipewire", + "flags": [ + "--ro-bind-try", "$XDG_RUNTIME_DIR/pipewire-0", "/run/user/$UID/pipewire-0" + ] + }, + { + "name": "pulseaudio", + "flags": [ + "--ro-bind-try", "$XDG_RUNTIME_DIR/pulse", "/run/user/$UID/pulse", + "--ro-bind-try", "/etc/pulse", "/etc/pulse" + ] + }, + { "name": "session" }, + { "name": "user" }, + { "name": "uts" }, + { + "name": "wayland", + "flags": [ + "--ro-bind-try", "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY", "/run/user/$UID/wayland-0", + "--ro-bind-try", "/usr/share/X11", "/usr/share/X11", + "--setenv", "WAYLAND_DISPLAY", "wayland-0", + "--setenv", "_JAVA_AWT_WM_NONPARENTING", "1", + "--setenv", "MOZ_ENABLE_WAYLAND", "1", + "--setenv", "XDG_SESSION_TYPE", "wayland" + ] + }, + { + "name": "x11", + "flags": [ + "--ro-bind-try", "$XAUTHORITY","$HOME/.Xauthority", + "--ro-bind-try", "$TMPDIR/.X11-unix/X$DISPLAY", "/usr/share/X11", + "--ro-bind-try", "/usr/share/X11", "/usr/share/X11", + "--setenv", "XAUTHORITY", "$HOME/.Xauthority" + ] + } +]