Skip to content

Commit

Permalink
Initial implementation for service sharing
Browse files Browse the repository at this point in the history
This is a very basic implementation of service sharing between strata,
it simply forwards systemd services to
/bedrock/cross/services/<stratum-name> and replaces the Start commands
in them with strat-using ones. Somehow, the security features of
"systemd" seem to not bother it now, even though previously in my
testing they did. After symlinking a service from cross to
/etc/systemd/ it works in the main stratum.
  • Loading branch information
vaartis committed Jul 27, 2020
1 parent 93ebc55 commit c812505
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 117 deletions.
279 changes: 164 additions & 115 deletions src/crossfs/crossfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ enum filter {
* Combine fonts.dir and fonts.aliases files.
*/
FILTER_FONT,

FILTER_SERVICE,
/*
* Pass file through unaltered.
*/
Expand All @@ -289,6 +291,7 @@ const char *const filter_str[] = {
"bin-restrict",
"ini",
"font",
"service",
"pass",
};

Expand Down Expand Up @@ -1715,6 +1718,60 @@ static inline int set_local_stratum(void)
return 0;
}

static inline void getattr_ini(struct cfg_entry *cfg, const char *ipath, size_t ipath_len, struct stat *stbuf, int *rv) {
if (!S_ISREG(stbuf->st_mode)) {
return;
}

struct back_entry *back;
char bpath[PATH_MAX];
*rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
if (rv < 0) {
*rv = -errno;

return;
}

FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
if (fp == NULL) {
*rv = -errno;

return;
}

char line[PATH_MAX];
while (fgets(line, sizeof(line), fp) != NULL) {
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
i++) {
/*
* No ini_inject_strat_len will exceed line's PATH_MAX,
* this should be safe.
*/
if (strncmp(line, ini_inject_strat_str[i],
ini_inject_strat_len[i]) != 0) {
continue;
}
stbuf->st_size += STRAT_PATH_LEN;
stbuf->st_size += strlen(" ");
stbuf->st_size += deref(back)->name_len;
stbuf->st_size += strlen(" ");
break;
}
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
i++) {
if (strncmp(line, ini_expand_path_str[i],
ini_expand_path_len[i]) != 0
|| line[ini_expand_path_len[i]] !=
'/') {
continue;
}
stbuf->st_size += STRATA_ROOT_LEN;
stbuf->st_size += deref(back)->name_len;
}
}
fclose(fp);
}

static inline int getattr_back(struct cfg_entry *cfg, const char *ipath,
size_t ipath_len, struct stat *stbuf)
{
Expand All @@ -1741,58 +1798,25 @@ static inline int getattr_back(struct cfg_entry *cfg, const char *ipath,
}
break;

case FILTER_INI:
if (!S_ISREG(stbuf->st_mode)) {
break;
}

struct back_entry *back;
case FILTER_SERVICE:
;
struct back_entry *back;
char bpath[PATH_MAX];
rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
if (rv < 0) {
rv = -errno;
break;
}

FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
if (fp == NULL) {
rv = -errno;
break;
}
if (strstr(bpath, "systemd")) {
getattr_ini(cfg, ipath, ipath_len, stbuf, &rv);
}

char line[PATH_MAX];
while (fgets(line, sizeof(line), fp) != NULL) {
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
i++) {
/*
* No ini_inject_strat_len will exceed line's PATH_MAX,
* this should be safe.
*/
if (strncmp(line, ini_inject_strat_str[i],
ini_inject_strat_len[i]) != 0) {
continue;
}
stbuf->st_size += STRAT_PATH_LEN;
stbuf->st_size += strlen(" ");
stbuf->st_size += deref(back)->name_len;
stbuf->st_size += strlen(" ");
break;
}
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
i++) {
if (strncmp(line, ini_expand_path_str[i],
ini_expand_path_len[i]) != 0
|| line[ini_expand_path_len[i]] !=
'/') {
continue;
}
stbuf->st_size += STRATA_ROOT_LEN;
stbuf->st_size += deref(back)->name_len;
}
}
fclose(fp);
break;
break;
case FILTER_INI:
getattr_ini(cfg, ipath, ipath_len, stbuf, &rv);

break;
case FILTER_FONT:
;
/*
Expand Down Expand Up @@ -2078,6 +2102,89 @@ static inline int read_pass(struct cfg_entry *cfg, const char *const ipath,
return rv;
}

static inline int inject_ini(struct cfg_entry *cfg, const char *ipath, size_t ipath_len, char *buf, size_t size, off_t offset) {
struct back_entry *back;
char bpath[PATH_MAX];
int rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
if (rv < 0) {
return -errno;
}

FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
if (fp == NULL) {
return -errno;
}

size_t wrote = 0;
char line[PATH_MAX];
if (offset < 0) {
return -EINVAL;
}

size_t off = offset;
while (fgets(line, sizeof(line), fp) != NULL) {
int found = 0;
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
i++) {
if (strncmp(line, ini_inject_strat_str[i],
ini_inject_strat_len[i]) != 0) {
continue;
}
strcatoff(buf, ini_inject_strat_str[i],
ini_inject_strat_len[i], &off, &wrote,
size);
strcatoff(buf, STRAT_PATH, STRAT_PATH_LEN, &off,
&wrote, size);
strcatoff(buf, " ", 1, &off, &wrote, size);
strcatoff(buf, deref(back)->name,
deref(back)->name_len, &off, &wrote,
size);
strcatoff(buf, " ", 1, &off, &wrote, size);
strcatoff(buf, line + ini_inject_strat_len[i],
strlen(line + ini_inject_strat_len[i]),
&off, &wrote, size);
found = 1;
break;
}
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
i++) {
if (strncmp(line, ini_expand_path_str[i],
ini_expand_path_len[i]) != 0
|| line[ini_expand_path_len[i]] !=
'/') {
continue;
}
strcatoff(buf, ini_expand_path_str[i],
ini_expand_path_len[i], &off, &wrote,
size);
strcatoff(buf, STRATA_ROOT, STRATA_ROOT_LEN,
&off, &wrote, size);
strcatoff(buf, deref(back)->name,
deref(back)->name_len, &off, &wrote,
size);
strcatoff(buf, line + ini_expand_path_len[i],
strlen(line + ini_expand_path_len[i]),
&off, &wrote, size);
found = 1;
}
if (!found) {
strcatoff(buf, line, strlen(line), &off,
&wrote, size);
}
if (wrote >= size) {
break;
}
}
rv = wrote;
fclose(fp);

return rv;
}

static inline int read_systemd_service(struct cfg_entry *cfg, const char *const ipath, size_t ipath_len, char *buf, size_t size, off_t offset) {
return inject_ini(cfg, ipath, ipath_len, buf, size, offset);
}

static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
ipath_len, char *buf, size_t size, off_t offset)
{
Expand All @@ -2089,84 +2196,26 @@ static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
rv = pread(bouncer_fd, buf, size, offset);
break;

case FILTER_INI:
;
struct back_entry *back;
case FILTER_SERVICE:
;
struct back_entry *back;
char bpath[PATH_MAX];
rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
if (rv < 0) {
rv = -errno;
break;
}

FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
if (fp == NULL) {
rv = -errno;
break;
}
if (strstr(bpath, "systemd")) {
rv = read_systemd_service(cfg, ipath, ipath_len, buf, size, offset);
} else {
rv = read_pass(cfg, ipath, ipath_len, buf, size, offset);
}

size_t wrote = 0;
char line[PATH_MAX];
if (offset < 0) {
rv = -EINVAL;
break;
}
size_t off = offset;
while (fgets(line, sizeof(line), fp) != NULL) {
int found = 0;
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
i++) {
if (strncmp(line, ini_inject_strat_str[i],
ini_inject_strat_len[i]) != 0) {
continue;
}
strcatoff(buf, ini_inject_strat_str[i],
ini_inject_strat_len[i], &off, &wrote,
size);
strcatoff(buf, STRAT_PATH, STRAT_PATH_LEN, &off,
&wrote, size);
strcatoff(buf, " ", 1, &off, &wrote, size);
strcatoff(buf, deref(back)->name,
deref(back)->name_len, &off, &wrote,
size);
strcatoff(buf, " ", 1, &off, &wrote, size);
strcatoff(buf, line + ini_inject_strat_len[i],
strlen(line + ini_inject_strat_len[i]),
&off, &wrote, size);
found = 1;
break;
}
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
i++) {
if (strncmp(line, ini_expand_path_str[i],
ini_expand_path_len[i]) != 0
|| line[ini_expand_path_len[i]] !=
'/') {
continue;
}
strcatoff(buf, ini_expand_path_str[i],
ini_expand_path_len[i], &off, &wrote,
size);
strcatoff(buf, STRATA_ROOT, STRATA_ROOT_LEN,
&off, &wrote, size);
strcatoff(buf, deref(back)->name,
deref(back)->name_len, &off, &wrote,
size);
strcatoff(buf, line + ini_expand_path_len[i],
strlen(line + ini_expand_path_len[i]),
&off, &wrote, size);
found = 1;
}
if (!found) {
strcatoff(buf, line, strlen(line), &off,
&wrote, size);
}
if (wrote >= size) {
break;
}
}
rv = wrote;
fclose(fp);
break;

case FILTER_INI:
rv = inject_ini(cfg, ipath, ipath_len, buf, size, offset);
break;

case FILTER_FONT:
Expand Down Expand Up @@ -2199,8 +2248,8 @@ static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
break;
}

wrote = 0;
off = offset;
size_t wrote = 0;
size_t off = offset;

/*
* Handle line count line
Expand Down
3 changes: 3 additions & 0 deletions src/slash-bedrock/etc/bedrock.conf
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,9 @@ dbus-session = /usr/share/dbus-1/services
#
fonts = /usr/share/fonts

[cross-service]
usr/lib/systemd = /usr/lib/systemd

[pmm]
#
# Package Manager Manager
Expand Down
10 changes: 8 additions & 2 deletions src/slash-bedrock/share/common-code
Original file line number Diff line number Diff line change
Expand Up @@ -1382,9 +1382,15 @@ cfg_crossfs() {
continue
}

target = filter" /"key" "n_strata[i]":"n_values[j]
if (filter == "service") {
# for services, use a different path
target = filter" /services/"n_strata[i]"/"key" "n_strata[i]":"n_values[j]
} else {
target = filter" /"key" "n_strata[i]":"n_values[j]
}

if (!(target in targets)) {
n_targets[++targets_len] = target
n_targets[++targets_len] = target
targets[target] = target
}
}
Expand Down

0 comments on commit c812505

Please sign in to comment.