Skip to content

Commit c812505

Browse files
committed
Initial implementation for service sharing
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.
1 parent 93ebc55 commit c812505

3 files changed

Lines changed: 175 additions & 117 deletions

File tree

src/crossfs/crossfs.c

Lines changed: 164 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ enum filter {
278278
* Combine fonts.dir and fonts.aliases files.
279279
*/
280280
FILTER_FONT,
281+
282+
FILTER_SERVICE,
281283
/*
282284
* Pass file through unaltered.
283285
*/
@@ -289,6 +291,7 @@ const char *const filter_str[] = {
289291
"bin-restrict",
290292
"ini",
291293
"font",
294+
"service",
292295
"pass",
293296
};
294297

@@ -1715,6 +1718,60 @@ static inline int set_local_stratum(void)
17151718
return 0;
17161719
}
17171720

1721+
static inline void getattr_ini(struct cfg_entry *cfg, const char *ipath, size_t ipath_len, struct stat *stbuf, int *rv) {
1722+
if (!S_ISREG(stbuf->st_mode)) {
1723+
return;
1724+
}
1725+
1726+
struct back_entry *back;
1727+
char bpath[PATH_MAX];
1728+
*rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
1729+
if (rv < 0) {
1730+
*rv = -errno;
1731+
1732+
return;
1733+
}
1734+
1735+
FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
1736+
if (fp == NULL) {
1737+
*rv = -errno;
1738+
1739+
return;
1740+
}
1741+
1742+
char line[PATH_MAX];
1743+
while (fgets(line, sizeof(line), fp) != NULL) {
1744+
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
1745+
i++) {
1746+
/*
1747+
* No ini_inject_strat_len will exceed line's PATH_MAX,
1748+
* this should be safe.
1749+
*/
1750+
if (strncmp(line, ini_inject_strat_str[i],
1751+
ini_inject_strat_len[i]) != 0) {
1752+
continue;
1753+
}
1754+
stbuf->st_size += STRAT_PATH_LEN;
1755+
stbuf->st_size += strlen(" ");
1756+
stbuf->st_size += deref(back)->name_len;
1757+
stbuf->st_size += strlen(" ");
1758+
break;
1759+
}
1760+
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
1761+
i++) {
1762+
if (strncmp(line, ini_expand_path_str[i],
1763+
ini_expand_path_len[i]) != 0
1764+
|| line[ini_expand_path_len[i]] !=
1765+
'/') {
1766+
continue;
1767+
}
1768+
stbuf->st_size += STRATA_ROOT_LEN;
1769+
stbuf->st_size += deref(back)->name_len;
1770+
}
1771+
}
1772+
fclose(fp);
1773+
}
1774+
17181775
static inline int getattr_back(struct cfg_entry *cfg, const char *ipath,
17191776
size_t ipath_len, struct stat *stbuf)
17201777
{
@@ -1741,58 +1798,25 @@ static inline int getattr_back(struct cfg_entry *cfg, const char *ipath,
17411798
}
17421799
break;
17431800

1744-
case FILTER_INI:
1745-
if (!S_ISREG(stbuf->st_mode)) {
1746-
break;
1747-
}
1748-
1749-
struct back_entry *back;
1801+
case FILTER_SERVICE:
1802+
;
1803+
struct back_entry *back;
17501804
char bpath[PATH_MAX];
17511805
rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
17521806
if (rv < 0) {
17531807
rv = -errno;
17541808
break;
17551809
}
17561810

1757-
FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
1758-
if (fp == NULL) {
1759-
rv = -errno;
1760-
break;
1761-
}
1811+
if (strstr(bpath, "systemd")) {
1812+
getattr_ini(cfg, ipath, ipath_len, stbuf, &rv);
1813+
}
17621814

1763-
char line[PATH_MAX];
1764-
while (fgets(line, sizeof(line), fp) != NULL) {
1765-
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
1766-
i++) {
1767-
/*
1768-
* No ini_inject_strat_len will exceed line's PATH_MAX,
1769-
* this should be safe.
1770-
*/
1771-
if (strncmp(line, ini_inject_strat_str[i],
1772-
ini_inject_strat_len[i]) != 0) {
1773-
continue;
1774-
}
1775-
stbuf->st_size += STRAT_PATH_LEN;
1776-
stbuf->st_size += strlen(" ");
1777-
stbuf->st_size += deref(back)->name_len;
1778-
stbuf->st_size += strlen(" ");
1779-
break;
1780-
}
1781-
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
1782-
i++) {
1783-
if (strncmp(line, ini_expand_path_str[i],
1784-
ini_expand_path_len[i]) != 0
1785-
|| line[ini_expand_path_len[i]] !=
1786-
'/') {
1787-
continue;
1788-
}
1789-
stbuf->st_size += STRATA_ROOT_LEN;
1790-
stbuf->st_size += deref(back)->name_len;
1791-
}
1792-
}
1793-
fclose(fp);
1794-
break;
1815+
break;
1816+
case FILTER_INI:
1817+
getattr_ini(cfg, ipath, ipath_len, stbuf, &rv);
17951818

1819+
break;
17961820
case FILTER_FONT:
17971821
;
17981822
/*
@@ -2078,6 +2102,89 @@ static inline int read_pass(struct cfg_entry *cfg, const char *const ipath,
20782102
return rv;
20792103
}
20802104

2105+
static inline int inject_ini(struct cfg_entry *cfg, const char *ipath, size_t ipath_len, char *buf, size_t size, off_t offset) {
2106+
struct back_entry *back;
2107+
char bpath[PATH_MAX];
2108+
int rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
2109+
if (rv < 0) {
2110+
return -errno;
2111+
}
2112+
2113+
FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
2114+
if (fp == NULL) {
2115+
return -errno;
2116+
}
2117+
2118+
size_t wrote = 0;
2119+
char line[PATH_MAX];
2120+
if (offset < 0) {
2121+
return -EINVAL;
2122+
}
2123+
2124+
size_t off = offset;
2125+
while (fgets(line, sizeof(line), fp) != NULL) {
2126+
int found = 0;
2127+
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
2128+
i++) {
2129+
if (strncmp(line, ini_inject_strat_str[i],
2130+
ini_inject_strat_len[i]) != 0) {
2131+
continue;
2132+
}
2133+
strcatoff(buf, ini_inject_strat_str[i],
2134+
ini_inject_strat_len[i], &off, &wrote,
2135+
size);
2136+
strcatoff(buf, STRAT_PATH, STRAT_PATH_LEN, &off,
2137+
&wrote, size);
2138+
strcatoff(buf, " ", 1, &off, &wrote, size);
2139+
strcatoff(buf, deref(back)->name,
2140+
deref(back)->name_len, &off, &wrote,
2141+
size);
2142+
strcatoff(buf, " ", 1, &off, &wrote, size);
2143+
strcatoff(buf, line + ini_inject_strat_len[i],
2144+
strlen(line + ini_inject_strat_len[i]),
2145+
&off, &wrote, size);
2146+
found = 1;
2147+
break;
2148+
}
2149+
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
2150+
i++) {
2151+
if (strncmp(line, ini_expand_path_str[i],
2152+
ini_expand_path_len[i]) != 0
2153+
|| line[ini_expand_path_len[i]] !=
2154+
'/') {
2155+
continue;
2156+
}
2157+
strcatoff(buf, ini_expand_path_str[i],
2158+
ini_expand_path_len[i], &off, &wrote,
2159+
size);
2160+
strcatoff(buf, STRATA_ROOT, STRATA_ROOT_LEN,
2161+
&off, &wrote, size);
2162+
strcatoff(buf, deref(back)->name,
2163+
deref(back)->name_len, &off, &wrote,
2164+
size);
2165+
strcatoff(buf, line + ini_expand_path_len[i],
2166+
strlen(line + ini_expand_path_len[i]),
2167+
&off, &wrote, size);
2168+
found = 1;
2169+
}
2170+
if (!found) {
2171+
strcatoff(buf, line, strlen(line), &off,
2172+
&wrote, size);
2173+
}
2174+
if (wrote >= size) {
2175+
break;
2176+
}
2177+
}
2178+
rv = wrote;
2179+
fclose(fp);
2180+
2181+
return rv;
2182+
}
2183+
2184+
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) {
2185+
return inject_ini(cfg, ipath, ipath_len, buf, size, offset);
2186+
}
2187+
20812188
static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
20822189
ipath_len, char *buf, size_t size, off_t offset)
20832190
{
@@ -2089,84 +2196,26 @@ static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
20892196
rv = pread(bouncer_fd, buf, size, offset);
20902197
break;
20912198

2092-
case FILTER_INI:
2093-
;
2094-
struct back_entry *back;
2199+
case FILTER_SERVICE:
2200+
;
2201+
struct back_entry *back;
20952202
char bpath[PATH_MAX];
20962203
rv = loc_first_bpath(cfg, ipath, ipath_len, &back, bpath);
20972204
if (rv < 0) {
20982205
rv = -errno;
20992206
break;
21002207
}
21012208

2102-
FILE *fp = fchroot_fopen_rdonly(deref(back)->root_fd, bpath);
2103-
if (fp == NULL) {
2104-
rv = -errno;
2105-
break;
2106-
}
2209+
if (strstr(bpath, "systemd")) {
2210+
rv = read_systemd_service(cfg, ipath, ipath_len, buf, size, offset);
2211+
} else {
2212+
rv = read_pass(cfg, ipath, ipath_len, buf, size, offset);
2213+
}
21072214

2108-
size_t wrote = 0;
2109-
char line[PATH_MAX];
2110-
if (offset < 0) {
2111-
rv = -EINVAL;
2112-
break;
2113-
}
2114-
size_t off = offset;
2115-
while (fgets(line, sizeof(line), fp) != NULL) {
2116-
int found = 0;
2117-
for (size_t i = 0; i < ARRAY_LEN(ini_inject_strat_str);
2118-
i++) {
2119-
if (strncmp(line, ini_inject_strat_str[i],
2120-
ini_inject_strat_len[i]) != 0) {
2121-
continue;
2122-
}
2123-
strcatoff(buf, ini_inject_strat_str[i],
2124-
ini_inject_strat_len[i], &off, &wrote,
2125-
size);
2126-
strcatoff(buf, STRAT_PATH, STRAT_PATH_LEN, &off,
2127-
&wrote, size);
2128-
strcatoff(buf, " ", 1, &off, &wrote, size);
2129-
strcatoff(buf, deref(back)->name,
2130-
deref(back)->name_len, &off, &wrote,
2131-
size);
2132-
strcatoff(buf, " ", 1, &off, &wrote, size);
2133-
strcatoff(buf, line + ini_inject_strat_len[i],
2134-
strlen(line + ini_inject_strat_len[i]),
2135-
&off, &wrote, size);
2136-
found = 1;
2137-
break;
2138-
}
2139-
for (size_t i = 0; i < ARRAY_LEN(ini_expand_path_str);
2140-
i++) {
2141-
if (strncmp(line, ini_expand_path_str[i],
2142-
ini_expand_path_len[i]) != 0
2143-
|| line[ini_expand_path_len[i]] !=
2144-
'/') {
2145-
continue;
2146-
}
2147-
strcatoff(buf, ini_expand_path_str[i],
2148-
ini_expand_path_len[i], &off, &wrote,
2149-
size);
2150-
strcatoff(buf, STRATA_ROOT, STRATA_ROOT_LEN,
2151-
&off, &wrote, size);
2152-
strcatoff(buf, deref(back)->name,
2153-
deref(back)->name_len, &off, &wrote,
2154-
size);
2155-
strcatoff(buf, line + ini_expand_path_len[i],
2156-
strlen(line + ini_expand_path_len[i]),
2157-
&off, &wrote, size);
2158-
found = 1;
2159-
}
2160-
if (!found) {
2161-
strcatoff(buf, line, strlen(line), &off,
2162-
&wrote, size);
2163-
}
2164-
if (wrote >= size) {
2165-
break;
2166-
}
2167-
}
2168-
rv = wrote;
2169-
fclose(fp);
2215+
break;
2216+
2217+
case FILTER_INI:
2218+
rv = inject_ini(cfg, ipath, ipath_len, buf, size, offset);
21702219
break;
21712220

21722221
case FILTER_FONT:
@@ -2199,8 +2248,8 @@ static inline int read_back(struct cfg_entry *cfg, const char *ipath, size_t
21992248
break;
22002249
}
22012250

2202-
wrote = 0;
2203-
off = offset;
2251+
size_t wrote = 0;
2252+
size_t off = offset;
22042253

22052254
/*
22062255
* Handle line count line

src/slash-bedrock/etc/bedrock.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ dbus-session = /usr/share/dbus-1/services
445445
#
446446
fonts = /usr/share/fonts
447447

448+
[cross-service]
449+
usr/lib/systemd = /usr/lib/systemd
450+
448451
[pmm]
449452
#
450453
# Package Manager Manager

src/slash-bedrock/share/common-code

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,9 +1382,15 @@ cfg_crossfs() {
13821382
continue
13831383
}
13841384

1385-
target = filter" /"key" "n_strata[i]":"n_values[j]
1385+
if (filter == "service") {
1386+
# for services, use a different path
1387+
target = filter" /services/"n_strata[i]"/"key" "n_strata[i]":"n_values[j]
1388+
} else {
1389+
target = filter" /"key" "n_strata[i]":"n_values[j]
1390+
}
1391+
13861392
if (!(target in targets)) {
1387-
n_targets[++targets_len] = target
1393+
n_targets[++targets_len] = target
13881394
targets[target] = target
13891395
}
13901396
}

0 commit comments

Comments
 (0)