mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-16 14:16:16 -06:00
experimental: remounts child mount points as well (read-only, read-write, noexec)
This commit is contained in:
parent
5df7c4d862
commit
a7164cb381
5 changed files with 305 additions and 94 deletions
|
|
@ -440,8 +440,10 @@ void preproc_clean_run(void);
|
|||
void fs_blacklist(void);
|
||||
// remount a directory read-only
|
||||
void fs_rdonly(const char *dir);
|
||||
void fs_rdonly_rec(const char *dir);
|
||||
// remount a directory noexec, nodev and nosuid
|
||||
void fs_noexec(const char *dir);
|
||||
void fs_noexec_rec(const char *dir);
|
||||
// mount /proc and /sys directories
|
||||
void fs_proc_sys_dev_boot(void);
|
||||
// build a basic read-only filesystem
|
||||
|
|
@ -550,12 +552,16 @@ int invalid_sandbox(const pid_t pid);
|
|||
// The return value points to a static area, and will be overwritten by subsequent calls.
|
||||
// The function does an exit(1) if anything goes wrong.
|
||||
typedef struct {
|
||||
int mountid; // id of the mount
|
||||
char *fsname; // the pathname of the directory in the filesystem which forms the root of this mount
|
||||
char *dir; // mount destination
|
||||
char *fstype; // filesystem type
|
||||
} MountData;
|
||||
MountData *get_last_mount(void);
|
||||
|
||||
// mountinfo.c
|
||||
MountData *get_last_mount(void);
|
||||
int get_mount_id(const char *path);
|
||||
char **get_all_mounts(const int mountid, const char *path);
|
||||
|
||||
// fs_var.c
|
||||
void fs_var_log(void); // mounting /var/log
|
||||
|
|
|
|||
|
|
@ -29,12 +29,14 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define MAX_BUF 4096
|
||||
// check noblacklist statements not matched by a proper blacklist in disable-*.inc files
|
||||
//#define TEST_NO_BLACKLIST_MATCHING
|
||||
|
||||
|
||||
|
||||
static void fs_rdwr(const char *dir);
|
||||
static void fs_rdwr_rec(const char *dir);
|
||||
|
||||
|
||||
|
||||
|
|
@ -147,21 +149,15 @@ static void disable_file(OPERATION op, const char *filename) {
|
|||
}
|
||||
}
|
||||
else if (op == MOUNT_READONLY) {
|
||||
if (arg_debug)
|
||||
printf("Mounting read-only %s\n", fname);
|
||||
fs_rdonly(fname);
|
||||
fs_rdonly_rec(fname);
|
||||
// todo: last_disable = SUCCESSFUL;
|
||||
}
|
||||
else if (op == MOUNT_RDWR) {
|
||||
if (arg_debug)
|
||||
printf("Mounting read-only %s\n", fname);
|
||||
fs_rdwr(fname);
|
||||
fs_rdwr_rec(fname);
|
||||
// todo: last_disable = SUCCESSFUL;
|
||||
}
|
||||
else if (op == MOUNT_NOEXEC) {
|
||||
if (arg_debug)
|
||||
printf("Mounting noexec %s\n", fname);
|
||||
fs_noexec(fname);
|
||||
fs_noexec_rec(fname);
|
||||
// todo: last_disable = SUCCESSFUL;
|
||||
}
|
||||
else if (op == MOUNT_TMPFS) {
|
||||
|
|
@ -457,9 +453,10 @@ static int get_mount_flags(const char *path, unsigned long *flags) {
|
|||
|
||||
//***********************************************
|
||||
// mount namespace
|
||||
// - functions need fully resolved paths
|
||||
//***********************************************
|
||||
|
||||
// remount a directory read-only
|
||||
// remount directory read-only
|
||||
void fs_rdonly(const char *dir) {
|
||||
assert(dir);
|
||||
// check directory exists
|
||||
|
|
@ -471,77 +468,138 @@ void fs_rdonly(const char *dir) {
|
|||
if ((flags & MS_RDONLY) == MS_RDONLY)
|
||||
return;
|
||||
flags |= MS_RDONLY;
|
||||
if (arg_debug)
|
||||
printf("Mounting read-only %s\n", dir);
|
||||
// mount --bind /bin /bin
|
||||
// mount --bind -o remount,ro /bin
|
||||
if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
|
||||
mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
|
||||
errExit("mount read-only");
|
||||
fs_logger2("read-only", dir);
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_rdwr(const char *dir) {
|
||||
// remount directory read-only recursively
|
||||
void fs_rdonly_rec(const char *dir) {
|
||||
assert(dir);
|
||||
// check directory exists and ensure we have a resolved path
|
||||
// the resolved path allows to run a sanity check after the mount
|
||||
char *path = realpath(dir, NULL);
|
||||
if (path == NULL)
|
||||
return;
|
||||
// allow only user owned directories, except the user is root
|
||||
uid_t u = getuid();
|
||||
struct stat s;
|
||||
int rv = stat(path, &s);
|
||||
if (rv) {
|
||||
free(path);
|
||||
EUID_USER();
|
||||
// get mount point of the directory
|
||||
int mountid = get_mount_id(dir);
|
||||
if (mountid == 0)
|
||||
return;
|
||||
// build array with all mount points that need to get remounted
|
||||
char **arr = get_all_mounts(mountid, dir);
|
||||
assert(arr);
|
||||
// remount
|
||||
EUID_ROOT();
|
||||
char **tmp = arr;
|
||||
while (*tmp) {
|
||||
fs_rdonly(*tmp);
|
||||
free(*tmp++);
|
||||
}
|
||||
if (u != 0 && s.st_uid != u) {
|
||||
fwarning("you are not allowed to change %s to read-write\n", path);
|
||||
free(path);
|
||||
return;
|
||||
}
|
||||
// mount --bind /bin /bin
|
||||
// mount --bind -o remount,rw /bin
|
||||
unsigned long flags = 0;
|
||||
get_mount_flags(path, &flags);
|
||||
if ((flags & MS_RDONLY) == 0) {
|
||||
free(path);
|
||||
return;
|
||||
}
|
||||
flags &= ~MS_RDONLY;
|
||||
if (mount(path, path, NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, path, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
|
||||
errExit("mount read-write");
|
||||
fs_logger2("read-write", path);
|
||||
|
||||
// run a check on /proc/self/mountinfo to validate the mount
|
||||
MountData *mptr = get_last_mount();
|
||||
if (strncmp(mptr->dir, path, strlen(path)) != 0)
|
||||
errLogExit("invalid read-write mount");
|
||||
|
||||
free(path);
|
||||
free(arr);
|
||||
}
|
||||
|
||||
// remount directory read-write
|
||||
static void fs_rdwr(const char *dir) {
|
||||
assert(dir);
|
||||
// check directory exists
|
||||
struct stat s;
|
||||
int rv = stat(dir, &s);
|
||||
if (rv == 0) {
|
||||
// allow only user owned directories, except the user is root
|
||||
uid_t u = getuid();
|
||||
if (u != 0 && s.st_uid != u) {
|
||||
fwarning("you are not allowed to change %s to read-write\n", dir);
|
||||
return;
|
||||
}
|
||||
unsigned long flags = 0;
|
||||
get_mount_flags(dir, &flags);
|
||||
if ((flags & MS_RDONLY) == 0)
|
||||
return;
|
||||
flags &= ~MS_RDONLY;
|
||||
if (arg_debug)
|
||||
printf("Mounting read-write %s\n", dir);
|
||||
// mount --bind /bin /bin
|
||||
// mount --bind -o remount,rw /bin
|
||||
if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
|
||||
errExit("mount read-write");
|
||||
fs_logger2("read-write", dir);
|
||||
// run a sanity check on /proc/self/mountinfo
|
||||
MountData *mptr = get_last_mount();
|
||||
size_t len = strlen(dir);
|
||||
if (strncmp(mptr->dir, dir, len) != 0 ||
|
||||
(*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/'))
|
||||
errLogExit("invalid read-write mount");
|
||||
}
|
||||
}
|
||||
|
||||
// remount directory read-write recursively
|
||||
static void fs_rdwr_rec(const char *dir) {
|
||||
assert(dir);
|
||||
EUID_USER();
|
||||
// get mount point of the directory
|
||||
int mountid = get_mount_id(dir);
|
||||
if (mountid == 0)
|
||||
return;
|
||||
// build array with all mount points that need to get remounted
|
||||
char **arr = get_all_mounts(mountid, dir);
|
||||
assert(arr);
|
||||
// remount
|
||||
EUID_ROOT();
|
||||
char **tmp = arr;
|
||||
while (*tmp) {
|
||||
fs_rdwr(*tmp);
|
||||
free(*tmp++);
|
||||
}
|
||||
free(arr);
|
||||
}
|
||||
|
||||
// remount directory noexec, nodev, nosuid
|
||||
void fs_noexec(const char *dir) {
|
||||
assert(dir);
|
||||
// check directory exists
|
||||
struct stat s;
|
||||
int rv = stat(dir, &s);
|
||||
if (rv == 0) {
|
||||
// mount --bind /bin /bin
|
||||
// mount --bind -o remount,ro /bin
|
||||
unsigned long flags = 0;
|
||||
get_mount_flags(dir, &flags);
|
||||
if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID))
|
||||
return;
|
||||
flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID;
|
||||
if (arg_debug)
|
||||
printf("Mounting noexec %s\n", dir);
|
||||
// mount --bind /bin /bin
|
||||
// mount --bind -o remount,noexec /bin
|
||||
if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
|
||||
mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0)
|
||||
errExit("mount noexec");
|
||||
fs_logger2("noexec", dir);
|
||||
}
|
||||
}
|
||||
|
||||
// remount directory noexec, nodev, nosuid recursively
|
||||
void fs_noexec_rec(const char *dir) {
|
||||
assert(dir);
|
||||
EUID_USER();
|
||||
// get mount point of the directory
|
||||
int mountid = get_mount_id(dir);
|
||||
if (mountid == 0)
|
||||
return;
|
||||
// build array with all mount points that need to get remounted
|
||||
char **arr = get_all_mounts(mountid, dir);
|
||||
assert(arr);
|
||||
// remount
|
||||
EUID_ROOT();
|
||||
char **tmp = arr;
|
||||
while (*tmp) {
|
||||
fs_noexec(*tmp);
|
||||
free(*tmp++);
|
||||
}
|
||||
free(arr);
|
||||
}
|
||||
|
||||
// Disable /mnt, /media, /run/mount and /run/media access
|
||||
void fs_mnt(const int enforce) {
|
||||
if (enforce) {
|
||||
|
|
|
|||
|
|
@ -19,16 +19,19 @@
|
|||
*/
|
||||
|
||||
#include "firejail.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
#define MAX_BUF 4096
|
||||
|
||||
static char mbuf[MAX_BUF];
|
||||
static MountData mdata;
|
||||
|
||||
|
||||
// Convert octal escape sequence to decimal value
|
||||
static int read_oct(const char *path) {
|
||||
int decimal = 0;
|
||||
int digit, i;
|
||||
// there are always three octal digits
|
||||
// there are always exactly three octal digits
|
||||
for (i = 1; i < 4; i++) {
|
||||
digit = *(path + i);
|
||||
if (digit < '0' || digit > '7') {
|
||||
|
|
@ -61,43 +64,38 @@ static void unmangle_path(char *path) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get info regarding the last kernel mount operation.
|
||||
// The return value points to a static area, and will be overwritten by subsequent calls.
|
||||
// The function does an exit(1) if anything goes wrong.
|
||||
MountData *get_last_mount(void) {
|
||||
// open /proc/self/mountinfo
|
||||
FILE *fp = fopen("/proc/self/mountinfo", "r");
|
||||
if (!fp)
|
||||
goto errexit;
|
||||
|
||||
mbuf[0] = '\0';
|
||||
while (fgets(mbuf, MAX_BUF, fp));
|
||||
fclose(fp);
|
||||
if (arg_debug)
|
||||
printf("%s", mbuf);
|
||||
|
||||
// extract filesystem name, directory and filesystem type
|
||||
// Parse a line from /proc/self/mountinfo,
|
||||
// the function does an exit(1) if anything goes wrong.
|
||||
static void parse_line(char *line, MountData *output) {
|
||||
assert(line && *line);
|
||||
memset(output, 0, sizeof(*output));
|
||||
// extract filesystem name, directory and filesystem types
|
||||
// examples:
|
||||
// 587 543 8:1 /tmp /etc rw,relatime master:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered
|
||||
// mdata.fsname: /tmp
|
||||
// mdata.dir: /etc
|
||||
// mdata.fstype: ext4
|
||||
// output.mountid: 587
|
||||
// output.fsname: /tmp
|
||||
// output.dir: /etc
|
||||
// output.fstype: ext4
|
||||
// 585 564 0:76 / /home/netblue/.cache rw,nosuid,nodev - tmpfs tmpfs rw
|
||||
// mdata.fsname: /
|
||||
// mdata.dir: /home/netblue/.cache
|
||||
// mdata.fstype: tmpfs
|
||||
memset(&mdata, 0, sizeof(mdata));
|
||||
char *ptr = strtok(mbuf, " ");
|
||||
// output.mountid: 585
|
||||
// output.fsname: /
|
||||
// output.dir: /home/netblue/.cache
|
||||
// output.fstype: tmpfs
|
||||
|
||||
char *ptr = strtok(line, " ");
|
||||
if (!ptr)
|
||||
goto errexit;
|
||||
|
||||
if (ptr != line)
|
||||
goto errexit;
|
||||
output->mountid = atoi(ptr);
|
||||
int cnt = 1;
|
||||
|
||||
while ((ptr = strtok(NULL, " ")) != NULL) {
|
||||
cnt++;
|
||||
if (cnt == 4)
|
||||
mdata.fsname = ptr;
|
||||
output->fsname = ptr;
|
||||
else if (cnt == 5) {
|
||||
mdata.dir = ptr;
|
||||
output->dir = ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,21 +107,156 @@ MountData *get_last_mount(void) {
|
|||
ptr = strtok(NULL, " ");
|
||||
if (!ptr)
|
||||
goto errexit;
|
||||
mdata.fstype = ptr++;
|
||||
output->fstype = ptr++;
|
||||
|
||||
if (mdata.fsname == NULL ||
|
||||
mdata.dir == NULL ||
|
||||
mdata.fstype == NULL)
|
||||
|
||||
if (output->mountid == 0 ||
|
||||
output->fsname == NULL ||
|
||||
output->dir == NULL ||
|
||||
output->fstype == NULL)
|
||||
goto errexit;
|
||||
|
||||
unmangle_path(mdata.fsname);
|
||||
unmangle_path(mdata.dir);
|
||||
// restore empty spaces
|
||||
unmangle_path(output->fsname);
|
||||
unmangle_path(output->dir);
|
||||
|
||||
if (arg_debug)
|
||||
printf("fsname=%s dir=%s fstype=%s\n", mdata.fsname, mdata.dir, mdata.fstype);
|
||||
return &mdata;
|
||||
return;
|
||||
|
||||
errexit:
|
||||
fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// The return value points to a static area, and will be overwritten by subsequent calls.
|
||||
MountData *get_last_mount(void) {
|
||||
// open /proc/self/mountinfo
|
||||
FILE *fp = fopen("/proc/self/mountinfo", "re");
|
||||
if (!fp) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mbuf[0] = '\0';
|
||||
// go to the last line
|
||||
while (fgets(mbuf, MAX_BUF, fp));
|
||||
fclose(fp);
|
||||
if (arg_debug)
|
||||
printf("%s", mbuf);
|
||||
|
||||
parse_line(mbuf, &mdata);
|
||||
|
||||
if (arg_debug)
|
||||
printf("mountid=%d fsname=%s dir=%s fstype=%s\n", mdata.mountid, mdata.fsname, mdata.dir, mdata.fstype);
|
||||
return &mdata;
|
||||
}
|
||||
|
||||
// Extract the mount id from /proc/self/fdinfo and return it.
|
||||
int get_mount_id(const char *path) {
|
||||
EUID_ASSERT();
|
||||
int fd = open(path, O_PATH|O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
char *fdinfo;
|
||||
if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1)
|
||||
errExit("asprintf");
|
||||
EUID_ROOT();
|
||||
FILE *fp = fopen(fdinfo, "re");
|
||||
EUID_USER();
|
||||
if (!fp)
|
||||
goto errexit;
|
||||
// go to the last line
|
||||
char buf[MAX_BUF];
|
||||
while (fgets(buf, MAX_BUF, fp));
|
||||
fclose(fp);
|
||||
close(fd);
|
||||
// go to the mount id
|
||||
if (strncmp(buf, "mnt_id:", 7) != 0)
|
||||
goto errexit;
|
||||
char *ptr = buf + 7;
|
||||
while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
|
||||
ptr++;
|
||||
}
|
||||
if (*ptr == '\0')
|
||||
goto errexit;
|
||||
free(fdinfo);
|
||||
|
||||
return atoi(ptr);
|
||||
|
||||
errexit:
|
||||
fprintf(stderr, "Error: cannot read file in /proc/self/fdinfo\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Return array with all paths that might need a remount.
|
||||
char **get_all_mounts(const int mountid, const char *path) {
|
||||
// open /proc/self/mountinfo
|
||||
FILE *fp = fopen("/proc/self/mountinfo", "re");
|
||||
if (!fp) {
|
||||
perror("fopen");
|
||||
fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t size = 32;
|
||||
size_t cnt = 0;
|
||||
char **rv = malloc(size * sizeof(*rv));
|
||||
if (!rv)
|
||||
errExit("malloc");
|
||||
|
||||
// read /proc/self/mountinfo
|
||||
size_t pathlen = strlen(path);
|
||||
int found = 0;
|
||||
while (fgets(mbuf, MAX_BUF, fp)) {
|
||||
// find mount point with mount id
|
||||
if (!found) {
|
||||
parse_line(mbuf, &mdata);
|
||||
if (mdata.mountid == mountid) {
|
||||
// don't remount blacklisted paths,
|
||||
// give up if mount id has been reassigned
|
||||
if (strstr(mdata.fsname, "firejail.ro.dir") ||
|
||||
strstr(mdata.fsname, "firejail.ro.file") ||
|
||||
strncmp(mdata.dir, path, strlen(mdata.dir)))
|
||||
break;
|
||||
|
||||
*rv = strdup(path);
|
||||
if (*rv == NULL)
|
||||
errExit("strdup");
|
||||
cnt++;
|
||||
found = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
// from here on add all mount points below path
|
||||
parse_line(mbuf, &mdata);
|
||||
if (strncmp(mdata.dir, path, pathlen) == 0 &&
|
||||
mdata.dir[pathlen] == '/' &&
|
||||
strstr(mdata.fsname, "firejail.ro.dir") == NULL &&
|
||||
strstr(mdata.fsname, "firejail.ro.file") == NULL) {
|
||||
|
||||
if (cnt >= size) {
|
||||
size *= 2;
|
||||
rv = realloc(rv, size * sizeof(*rv));
|
||||
if (!rv)
|
||||
errExit("realloc");
|
||||
}
|
||||
rv[cnt] = strdup(mdata.dir);
|
||||
if (!rv[cnt])
|
||||
errExit("strdup");
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if (cnt == size) {
|
||||
size++;
|
||||
rv = realloc(rv, size * sizeof(*rv));
|
||||
if (!rv)
|
||||
errExit("realloc");
|
||||
}
|
||||
rv[cnt] = NULL; // end of the array
|
||||
|
||||
fclose(fp);
|
||||
return rv;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "firejail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/mount.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -82,10 +83,8 @@ void pulseaudio_init(void) {
|
|||
// create the new user pulseaudio directory
|
||||
if (mkdir(RUN_PULSE_DIR, 0700) == -1)
|
||||
errExit("mkdir");
|
||||
// make it a mount point and add mount flags
|
||||
if (mount(RUN_PULSE_DIR, RUN_PULSE_DIR, NULL, MS_BIND, NULL) < 0 ||
|
||||
mount(NULL, RUN_PULSE_DIR, NULL, MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_BIND|MS_REMOUNT, NULL) < 0)
|
||||
errExit("mount RUN_PULSE_DIR");
|
||||
// mount it nosuid, noexec, nodev
|
||||
fs_noexec(RUN_PULSE_DIR);
|
||||
|
||||
// create the new client.conf file
|
||||
char *pulsecfg = NULL;
|
||||
|
|
@ -189,7 +188,12 @@ void pulseaudio_init(void) {
|
|||
// confirm the actual mount destination is owned by the user
|
||||
if (fstat(fd, &s) == -1 || s.st_uid != getuid())
|
||||
errExit("fstat");
|
||||
|
||||
// preserve a read-only mount
|
||||
struct statvfs vfs;
|
||||
if (fstatvfs(fd, &vfs) == -1)
|
||||
errExit("fstatvfs");
|
||||
if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
|
||||
fs_rdonly(RUN_PULSE_DIR);
|
||||
// mount via the link in /proc/self/fd
|
||||
char *proc;
|
||||
if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "firejail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -1163,6 +1164,9 @@ void x11_xorg(void) {
|
|||
unlink(tmpfname);
|
||||
umount("/tmp");
|
||||
|
||||
// remount RUN_XAUTHORITY_SEC_FILE noexec, nodev, nosuid
|
||||
fs_noexec(RUN_XAUTHORITY_SEC_FILE);
|
||||
|
||||
// Ensure there is already a file in the usual location, so that bind-mount below will work.
|
||||
char *dest;
|
||||
if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1)
|
||||
|
|
@ -1184,6 +1188,12 @@ void x11_xorg(void) {
|
|||
fprintf(stderr, "Error: .Xauthority is not a user owned regular file\n");
|
||||
exit(1);
|
||||
}
|
||||
// preserve a read-only mount
|
||||
struct statvfs vfs;
|
||||
if (fstatvfs(fd, &vfs) == -1)
|
||||
errExit("fstatvfs");
|
||||
if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
|
||||
fs_rdonly(RUN_XAUTHORITY_SEC_FILE);
|
||||
|
||||
// mount via the link in /proc/self/fd
|
||||
char *proc;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue