mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7fd5bc902 | ||
|
|
3f98220d5d | ||
|
|
0ca509a42e | ||
|
|
d17144d16f | ||
|
|
a608c5a5c9 | ||
|
|
9b44b99480 | ||
|
|
ad225156f1 | ||
|
|
eb92a915d3 | ||
|
|
69a4f2c115 | ||
|
|
9ce95fe8c0 | ||
|
|
06889cc014 | ||
|
|
329f11b4da | ||
|
|
ce40e2b9d2 | ||
|
|
d0176612c9 | ||
|
|
21753e26dd | ||
|
|
0dc2513b32 | ||
|
|
d16bfa789b | ||
|
|
0b27778c96 | ||
|
|
3e25297e3c | ||
|
|
6560968c8b | ||
|
|
c9a3c5c885 | ||
|
|
a2d45e8f5e | ||
|
|
f6c69eb108 | ||
|
|
f0032ab6b7 | ||
|
|
53c5d0e55a | ||
|
|
7c8ab7915f | ||
|
|
12f7855a78 | ||
|
|
bcc3360b53 | ||
|
|
d3408d14a8 | ||
|
|
804060444a | ||
|
|
de544a5b36 | ||
|
|
0d48d1df49 | ||
|
|
b46592e818 | ||
|
|
22bc218c84 |
@@ -40,23 +40,23 @@ jobs:
|
||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||
tar xf libuev-2.4.1.tar.xz
|
||||
tar xf libite-2.6.2.tar.gz
|
||||
(cd libuev-2.4.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||
sudo ldconfig
|
||||
- uses: actions/checkout@v4
|
||||
- name: Static Finit
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --prefix= --enable-static
|
||||
make -j3 V=1
|
||||
make -j9 V=1
|
||||
- name: Regular Finit
|
||||
run: |
|
||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||
--with-keventd --with-libsystemd \
|
||||
CFLAGS="-fsanitize=address -ggdb"
|
||||
make -j3 clean
|
||||
make -j3 V=1
|
||||
make -j9 clean
|
||||
make -j9 V=1
|
||||
- name: Install to /tmp
|
||||
run: |
|
||||
DESTDIR=/tmp make install-strip
|
||||
@@ -78,8 +78,9 @@ jobs:
|
||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
make check || (cat test/test-suite.log; false)
|
||||
make -j1 check || (cat test/test-suite.log; false)
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: finit-test-${{ matrix.compiler }}
|
||||
|
||||
@@ -60,8 +60,8 @@ jobs:
|
||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||
tar xf libuev-2.4.1.tar.xz
|
||||
tar xf libite-2.6.2.tar.gz
|
||||
(cd libuev-2.4.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||
sudo ldconfig
|
||||
- name: Configure
|
||||
run: |
|
||||
|
||||
+47
-15
@@ -19,12 +19,6 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -46,23 +40,61 @@ jobs:
|
||||
pipx inject mkdocs mkdocs-material
|
||||
pipx inject mkdocs pymdown-extensions
|
||||
pipx inject mkdocs mkdocs-callouts
|
||||
pipx inject mkdocs mkdocs-glightbox
|
||||
|
||||
- name: Build documentation
|
||||
run: mkdocs build
|
||||
run: mkdocs build --clean
|
||||
|
||||
- name: Upload Pages artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
- name: Upload site artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: site
|
||||
path: site/
|
||||
|
||||
deploy:
|
||||
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
- name: Download site artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: site
|
||||
path: site/
|
||||
|
||||
- name: Checkout pages repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: finit-project/finit-project.github.io
|
||||
path: pages
|
||||
ssh-key: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||
persist-credentials: true
|
||||
|
||||
- name: Setup SSH for push
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Sync site to pages repo
|
||||
run: |
|
||||
rsync -a --delete --exclude .git site/ pages/
|
||||
|
||||
- name: Commit and push
|
||||
run: |
|
||||
cd pages/
|
||||
if [ -z "$(git status --porcelain)" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SRC_REPO="${GITHUB_REPOSITORY}"
|
||||
SRC_REF="${GITHUB_SHA::7}"
|
||||
SRC_URL="https://github.com/${SRC_REPO}/commit/${SRC_REF}"
|
||||
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "actions@github.com"
|
||||
git add -A
|
||||
git commit -m "docs: update from ${SRC_REPO}@${SRC_REF}" \
|
||||
-m "For details, see ${SRC_URL}"
|
||||
git push
|
||||
|
||||
@@ -13,8 +13,6 @@ jobs:
|
||||
name: Build and upload release tarball
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
MAKEFLAGS: -j3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Installing dependencies ...
|
||||
@@ -25,8 +23,9 @@ jobs:
|
||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||
tar xf libuev-2.4.1.tar.xz
|
||||
tar xf libite-2.6.2.tar.gz
|
||||
(cd libuev-2.4.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||
sudo ldconfig
|
||||
- name: Setting release variables ...
|
||||
id: build
|
||||
run: |
|
||||
@@ -54,10 +53,21 @@ jobs:
|
||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Build release ...
|
||||
run: |
|
||||
make release || (cat test/test-suite.log; false)
|
||||
# Get version for finding distcheck build directory
|
||||
./configure --version | head -1
|
||||
ver=$(./configure --version | head -1 | awk '{print $NF}')
|
||||
dir=finit-$ver/_build/sub
|
||||
|
||||
make -j1 release || (cat $dir/test/test-suite.log; false)
|
||||
ls -lF ../
|
||||
mkdir -p artifacts/
|
||||
mv ../*.tar.* artifacts/
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: finit-release-test-logs
|
||||
path: finit-*/_build/sub/test/*.log
|
||||
- name: Extract ChangeLog entry ...
|
||||
run: |
|
||||
awk '/-----*/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|
||||
|
||||
@@ -14,14 +14,14 @@ jobs:
|
||||
schedule:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
run: ${{ steps.check.outputs.run }}
|
||||
run: ${{ steps.schedule.outputs.run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check for any commits since last week
|
||||
id: schedule
|
||||
run: |
|
||||
commits="$(git log --format=%H --since='1 week ago')"
|
||||
if [ -n "$commits" ]; then
|
||||
if [ -z "$commits" ]; then
|
||||
echo "run=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "run=false" >> $GITHUB_OUTPUT
|
||||
@@ -39,8 +39,9 @@ jobs:
|
||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||
tar xf libuev-2.4.1.tar.xz
|
||||
tar xf libite-2.6.2.tar.gz
|
||||
(cd libuev-2.4.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||
sudo ldconfig
|
||||
- uses: actions/checkout@v4
|
||||
- name: Base run
|
||||
run: |
|
||||
@@ -58,3 +59,9 @@ jobs:
|
||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||
dir=finit-$ver/_build/sub
|
||||
make -j1 distcheck || (cat $dir/test/test-suite.log; false)
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: finit-weekly-test-logs
|
||||
path: finit-*/_build/sub/test/*.log
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
[![License Badge][]][License] [![Release Badge][]][Release] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
||||
<img align="right" src="doc/img/finit3.png" alt="Finit: Fast Init">
|
||||
|
||||
Finit is an alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||
and [systemd](https://www.freedesktop.org/wiki/Software/systemd/), focused
|
||||
on small and embedded Linux systems, although fully usable on server and
|
||||
[desktop systems][finix].
|
||||
Finit is a fast, simple alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||
and [systemd](https://systemd.io), designed for small and embedded Linux systems.
|
||||
It can also run on desktop and server systems, like [finix][].
|
||||
|
||||
> Reverse engineered from the [EeePC fastinit][]
|
||||
> "gaps filled with frog DNA …"
|
||||
> — [Claudio Matsuoka][]
|
||||
|
||||
For detailed information, explore our extensive documentation
|
||||
:books: **<http://finit-project.github.io/finit/>**
|
||||
:books: **<http://finit-project.github.io>**
|
||||
|
||||
<div align="center">
|
||||
<img src="doc/img/alpine-screenshot2.png" alt="Alpine screenshot"><br/>
|
||||
@@ -26,14 +25,14 @@ tutorials:
|
||||
* :milky_way: [Void Linux](contrib/void/)
|
||||
|
||||
> [!NOTE]
|
||||
> Support for various Linux distributions does not mean Finit installs
|
||||
> easily on all architectures. Bundled install scripts are examples for
|
||||
> standard installations, tested on amd64 (x86_64) systems. Custom
|
||||
> setups, e.g., for embedded systems, can be found in the following
|
||||
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
||||
> [br2-finit-demo](https://github.com/finit-project/br2-finit-demo).
|
||||
> Finit can run on various Linux distributions, but the bundled install
|
||||
> scripts are examples only. They have been tested on amd64 (x86_64) systems
|
||||
> with standard configurations.
|
||||
>
|
||||
> For embedded systems, see these [Buildroot][]-based examples:
|
||||
> [myLinux][], [Infix][], or [br2-finit-demo][].
|
||||
|
||||
[finix]: https://github.com/aanderse/finix
|
||||
[finix]: https://github.com/finix-community/finix
|
||||
[Buildroot]: https://buildroot.org
|
||||
[Infix]: https://kernelkit.github.io
|
||||
[myLinux]: https://github.com/troglobit/myLinux/
|
||||
@@ -48,3 +47,4 @@ tutorials:
|
||||
[GitHub Status]: https://github.com/finit-project/finit/actions/workflows/build.yml/badge.svg
|
||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
||||
[br2-finit-demo]: https://github.com/finit-project/br2-finit-demo
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT([Finit], [4.15-rc1], [https://github.com/finit-project/finit/issues],
|
||||
AC_INIT([Finit], [4.15], [https://github.com/finit-project/finit/issues],
|
||||
[finit], [https://http://finit-project.github.io/])
|
||||
AC_CONFIG_AUX_DIR(aux)
|
||||
AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
|
||||
|
||||
+30
-2
@@ -3,9 +3,11 @@ Change Log
|
||||
|
||||
All relevant changes are documented in this file.
|
||||
|
||||
[4.15][UNRELEASED]
|
||||
[4.15][] - 2026-01-01
|
||||
---------------------
|
||||
|
||||
The Finit project now has a new home page: <https://finit-project.github.io>
|
||||
|
||||
### Changes
|
||||
- Change default reboot to SOC reset from WDT reset, issue #460
|
||||
- Bump required versions of libite (v2.6.2) and libuev (v2.4.1)
|
||||
@@ -24,17 +26,43 @@ All relevant changes are documented in this file.
|
||||
descriptive names like `/system/udevd/` instead of filename derived names
|
||||
like `/system/10-hotplug/`. Syntax supports combining with other options:
|
||||
`cgroup.system,name:foo,delegate,cpu.max:10000`
|
||||
- Add support for Linux capabilities, allowing services to run with minimal
|
||||
required privileges instead of running as root. Uses the modern IAB API
|
||||
(Inheritable, Ambient, Bounding) from libcap. By Aaron Andersen
|
||||
- Add support for supplementary groups for services. Uses the syntax
|
||||
`@user:group,sup1,sup2` to explicitly specify supplementary groups, in
|
||||
addition to reading group membership from `/etc/group`. By Aaron Andersen
|
||||
- Add CPU throttled information to `initctl` output, showing when a service
|
||||
has been throttled due to reaching its CPU quota
|
||||
- Add memory field to `initctl --json` status output for cgroup-enabled
|
||||
services
|
||||
- Default to user and group `root` (UID 0) for services
|
||||
- Always check that service user and group resolve to valid UID/GID pairs,
|
||||
otherwise log error and refuse to start service
|
||||
- Hide cursor at boot and shutdown for cleaner visual experience
|
||||
- Rename `tty` services early from `init` -> `getty` even though no getty
|
||||
process has been started yet. This to aid in boot timing detection using
|
||||
tools like `bootchartd` (BusyBox version or bootchart2 project) when Finit
|
||||
only shows *"Please press Enter to activate this console."*
|
||||
- Services with `respawn` option (including TTYs) now delay retry on non-zero
|
||||
exit codes instead of immediate respawn. Prevents busy-loop when service
|
||||
fails repeatedly, which on some systems may have a crippling effect
|
||||
|
||||
### Fixes
|
||||
- Fix #453: RTC plugin fixes by Ming Liu, Atlas Copco
|
||||
- Fix #455: ANSI escape sequences logged by tools using glib logging,
|
||||
caused by use of PTY instead of pipe for stdout/stderr redirection
|
||||
- Fix #462: `/dev/pts` mounted with wrong mode (400 instead of 620), causing
|
||||
permission issues with pseudo-terminals
|
||||
- getty: fix terminal scrollback issues after login on console TTY. Mouse
|
||||
scroll wheel and Shift+PgUp/PgDn sometimes would not work properly
|
||||
- Fix flickering and artifacts in `initctl top`
|
||||
- Fix file descriptor leak in `initctl top`
|
||||
- Fix incorrect "max" limit reporting in `initctl [top|cgroup|--json]` output
|
||||
for child cgroups. Resolves effective limits by walking the cgroup hierarchy
|
||||
- Fix issue with running Finit under `bootchartd` (bootchart2 project), always
|
||||
set `PATH` and `SHELL` envs early, before attempting to mount `/proc` et al
|
||||
- Always reset ownership and permissions on TTY device nodes before launching getty
|
||||
- Ensure mount/unmount skips `noauto` entries
|
||||
|
||||
|
||||
@@ -1885,7 +1913,7 @@ Major bug fix release.
|
||||
|
||||
* Initial release
|
||||
|
||||
[UNRELEASED]: https://github.com/finit-project/finit/compare/4.14...HEAD
|
||||
[UNRELEASED]: https://github.com/finit-project/finit/compare/4.15...HEAD
|
||||
[4.15]: https://github.com/finit-project/finit/compare/4.14...4.15
|
||||
[4.14]: https://github.com/finit-project/finit/compare/4.13...4.14
|
||||
[4.13]: https://github.com/troglobit/finit/compare/4.12...4.13
|
||||
|
||||
+20
-10
@@ -115,9 +115,10 @@ Common capabilities include (see `man 7 capabilities` for the complete list):
|
||||
- Only grant what the service actually needs
|
||||
- Don't grant `cap_sys_admin` unless absolutely necessary
|
||||
|
||||
2. **Always specify a user**
|
||||
- Always use `@user` to drop to a non-root user
|
||||
- Capabilities work best when combined with user separation
|
||||
2. **Specify a user (preferably non-root)**
|
||||
- The `@user` directive is **required** for `caps:` to take effect
|
||||
- For ambient capabilities (`^`), use a non-root user (not `@root`)
|
||||
- Example: `@www-data`, `@nginx`, `@tcpdump`
|
||||
|
||||
3. **Use ambient capabilities (`^`)**
|
||||
- The `^` prefix ensures capabilities survive exec()
|
||||
@@ -162,15 +163,24 @@ ps -o user,pid,cmd -p $(pidof nginx)
|
||||
|
||||
## Limitations
|
||||
|
||||
- Capabilities are only applied when both `@user` and `caps:` are specified
|
||||
- The service must drop to a non-root user for capabilities to be effective
|
||||
- The `caps:` directive requires `@user` to be specified for it to take effect
|
||||
- Without `@user`, the service runs as root with full capabilities and
|
||||
the `caps:` configuration is silently ignored
|
||||
- You can use `@root` with `caps:`, but see below about ambient capabilities
|
||||
- For ambient capabilities (`^`, recommended), the user **must be non-root**
|
||||
- Using `@root` with `caps:^...` will not work effectively, as ambient
|
||||
capabilities are only added to the effective set when euid ≠ 0
|
||||
- Use inheritable (`%`) or bounding (`!`) capabilities with `@root` if needed
|
||||
- Services without `caps:` use standard privilege dropping:
|
||||
- Services with `@user` (non-root) have no special capabilities
|
||||
- Services without `@user` run as root with full capabilities
|
||||
- Some very old binaries may not work correctly with ambient capabilities
|
||||
- File system capabilities are not managed by Finit (use `setcap` for that)
|
||||
|
||||
## See Also
|
||||
|
||||
- `man 7 capabilities` - Linux capabilities overview
|
||||
- `man 3 cap_iab` - IAB capability API documentation
|
||||
- `man 8 setcap` - Set file capabilities
|
||||
- `man 8 getcap` - Query file capabilities
|
||||
- `man 1 capsh` - Capability shell wrapper
|
||||
- [capabilities(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html) - Linux capabilities overview
|
||||
- [cap_iab(3)](https://man7.org/linux/man-pages/man3/cap_iab.3.html) - IAB capability API documentation
|
||||
- [setcap(8)](https://man7.org/linux/man-pages/man8/setcap.8.html) - Set file capabilities
|
||||
- [getcap(8)](https://man7.org/linux/man-pages/man8/getcap.8.html) - Query file capabilities
|
||||
- [capsh(1)](https://man7.org/linux/man-pages/man1/capsh.1.html) - Capability shell wrapper
|
||||
|
||||
@@ -127,11 +127,12 @@ Resource Limits
|
||||
Set the hard or soft limit for a resource, or both if that argument is
|
||||
omitted. `RESOURCE` is the lower-case `RLIMIT_` string constants from
|
||||
`setrlimit(2)`, without prefix. E.g. to set `RLIMIT_CPU`, use `cpu`.
|
||||
|
||||
|
||||
LIMIT is an integer that depends on the resource being modified, see
|
||||
the man page, or the kernel `/proc/PID/limits` file, for details.
|
||||
Finit versions before v3.1 used `infinity` for `unlimited`, which is
|
||||
still supported, albeit deprecated.
|
||||
[setrlimit(2)](https://man7.org/linux/man-pages/man2/setrlimit.2.html),
|
||||
or the kernel `/proc/PID/limits` file, for details. Finit versions
|
||||
before v3.1 used `infinity` for `unlimited`, which is still supported,
|
||||
albeit deprecated.
|
||||
|
||||
# No process is allowed more than 8MB of address space
|
||||
rlimit hard as 8388608
|
||||
|
||||
+16
-1
@@ -116,10 +116,25 @@ Non-privileged Services
|
||||
|
||||
Every `run`, `task`, or `service` can also list the privileges the
|
||||
`/path/to/cmd` should be executed with. Prefix the command with
|
||||
`@USR[:GRP]`, group is optional, like this:
|
||||
`@USR[:GRP[,SUPP,...]]`, where group and supplementary groups are
|
||||
optional, like this:
|
||||
|
||||
run [2345] @joe:users logger "Hello world"
|
||||
|
||||
Finit reads the user's supplementary group membership from `/etc/group`
|
||||
automatically. Any groups the user belongs to will be inherited by
|
||||
the service.
|
||||
|
||||
To specify additional supplementary groups beyond those in `/etc/group`,
|
||||
append them after the primary group, separated by commas:
|
||||
|
||||
service @caddy:caddy,ssl-cert /usr/bin/caddy run
|
||||
|
||||
This runs the `caddy` service as user `caddy`, with primary group
|
||||
`caddy`, inheriting any groups `caddy` is a member of in `/etc/group`,
|
||||
plus the additional `ssl-cert` group. This is useful when a service
|
||||
needs access to resources owned by groups not listed in `/etc/group`.
|
||||
|
||||
For multiple instances of the same command, e.g. a DHCP client or
|
||||
multiple web servers, add `:ID` somewhere between the `run`, `task`,
|
||||
`service` keyword and the command, like this:
|
||||
|
||||
+105
-46
@@ -1,80 +1,139 @@
|
||||
Distro Recommendations
|
||||
======================
|
||||
|
||||
By default Finit uses the following directories for configuration files:
|
||||
Finit supports two directory layouts for managing service configurations:
|
||||
|
||||
1. **Simple layout** - all configuration files directly in `/etc/finit.d/`
|
||||
2. **Distro layout** - separate `available/` and `enabled/` directories
|
||||
|
||||
The distro layout is recommended for distributions that need clear
|
||||
separation between installed and enabled services, and want to use the
|
||||
`initctl enable/disable` commands for service management.
|
||||
|
||||
## Simple Layout
|
||||
|
||||
Finit supports using a flat directory structure:
|
||||
|
||||
```
|
||||
/etc/
|
||||
|-- finit.d/ -- Regular (enabled) services
|
||||
|-- finit.d/ -- All enabled services
|
||||
| |-- lighttpd.conf
|
||||
| `- *.conf
|
||||
|-- finit.conf -- Bootstrap tasks and services
|
||||
:
|
||||
```
|
||||
|
||||
To enable a service one simply drops a small configuration file in the
|
||||
`/etc/finit.d/` directory. This practice works with systems that
|
||||
keep disabled services elsewhere, or generates them as needed from some
|
||||
other tool.
|
||||
In this layout, you enable a service by placing its `.conf` file in
|
||||
`/etc/finit.d/` and disable it by removing the file. This works well for
|
||||
embedded systems or custom setups where services are managed by other tools
|
||||
or generated dynamically.
|
||||
|
||||
Distributions, however, may want a clearer separation of enabled and
|
||||
available (installed but not enabled) services. They may even want to
|
||||
customize the directories used, for brand labeling or uniformity.
|
||||
> [!NOTE] No tooling support
|
||||
> The `initctl enable/disable` commands **do not work** with this layout.
|
||||
> You must manually manage files in `/etc/finit.d/`.
|
||||
|
||||
To that end Finit allows for a sub-directory `/etc/finit.d/available/`
|
||||
where installed but disabled services can reside. Adding a symlink to a
|
||||
configuration in this sub-directory enables the service, but it will not
|
||||
be started.
|
||||
## Distro Layout
|
||||
|
||||
To change the default configuration directory and configuration file
|
||||
names the Finit `configure` script offers the following two options at
|
||||
build time:
|
||||
Distributions typically want clearer separation between available (installed)
|
||||
and enabled services. Finit supports this through the `available/` and
|
||||
`enabled/` subdirectories:
|
||||
|
||||
```
|
||||
/etc/
|
||||
|-- finit.d/
|
||||
| |-- available/ -- Installed but disabled services
|
||||
| | |-- httpd.conf
|
||||
| | |-- ntpd.conf
|
||||
| | `-- sshd.conf
|
||||
| |-- enabled/ -- Enabled services (symlinks)
|
||||
| | `- sshd.conf -- Symlink to ../available/sshd.conf
|
||||
|-- finit.conf -- Bootstrap tasks and services
|
||||
:
|
||||
```
|
||||
|
||||
In this layout:
|
||||
- **available/** contains all installed service configurations
|
||||
- **enabled/** contains symlinks to configurations that should start at boot
|
||||
- Services are enabled/disabled by creating/removing symlinks
|
||||
|
||||
> [!IMPORTANT] Recommended
|
||||
> This is the recommended layout. In fact, the `initctl enable/disable`
|
||||
> commands **require** this layout with both `available/` and `enabled/`
|
||||
> directories and will not work without it.
|
||||
|
||||
## Managing Services with initctl
|
||||
|
||||
When using the distro layout, the `initctl` tool provides convenient commands
|
||||
for managing service configurations:
|
||||
|
||||
```
|
||||
list List all .conf in /etc/finit.d/
|
||||
enable <CONF> Enable .conf by creating symlink in enabled/
|
||||
disable <CONF> Disable .conf by removing symlink from enabled/
|
||||
reload Reload *.conf in /etc/finit.d/ (activate changes)
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```bash
|
||||
# Enable sshd (creates enabled/sshd.conf -> ../available/sshd.conf)
|
||||
initctl enable sshd
|
||||
|
||||
# Disable httpd (removes enabled/httpd.conf symlink)
|
||||
initctl disable httpd
|
||||
|
||||
# Apply changes (reload configuration and start/stop services)
|
||||
initctl reload
|
||||
```
|
||||
|
||||
The `.conf` suffix is optional - `initctl` adds it automatically if missing.
|
||||
|
||||
> [!NOTE] Remember `initctl reload`
|
||||
> Changes made with `enable`/`disable` take effect only after running
|
||||
> `initctl reload`, unless Finit was built with `--enable-auto-reload`
|
||||
> which automatically detects and applies configuration changes.
|
||||
|
||||
### Service Overrides
|
||||
|
||||
The `initctl` tool only operates on symlinks in the `enabled/` directory.
|
||||
If you place a regular (non-symlink) `.conf` file directly in the parent
|
||||
directory (e.g., `/etc/finit.d/`), `initctl` will ignore it. This allows
|
||||
you to create system-level overrides that cannot be accidentally disabled
|
||||
by package management tools.
|
||||
|
||||
## Customizing Directory Paths
|
||||
|
||||
Distributions can customize the directory names and locations at build time
|
||||
using the Finit `configure` script:
|
||||
|
||||
```sh
|
||||
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Remember `--prefix` et al as well, the default is likely *not* what
|
||||
> you want. See the [build docs][1] for details.
|
||||
This changes the default `/etc/finit.d/` to `/etc/init.d/` and moves the
|
||||
bootstrap configuration file accordingly.
|
||||
|
||||
The resulting directory structure is depicted below. Please notice how
|
||||
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
||||
`/etc/init.d/init.conf`:
|
||||
> [!IMPORTANT] Remember to set `--prefix`
|
||||
> Remember to set `--prefix` and related options appropriately. The default
|
||||
> prefix is `/usr/local`, which is likely not what you want for a system
|
||||
> init. See the [build documentation][1] for details.
|
||||
|
||||
Example with custom paths:
|
||||
|
||||
```
|
||||
/etc/
|
||||
|-- init.d/
|
||||
| |-- available/ -- Regular (disabled) services
|
||||
| |-- available/ -- Installed services
|
||||
| | |-- httpd.conf
|
||||
| | |-- ntpd.conf
|
||||
| | `-- sshd.conf
|
||||
| |-- sshd.conf -- Symlink to available/sshd.conf
|
||||
| |-- enabled/ -- Enabled services (symlinks)
|
||||
| | `- sshd.conf -- Symlink to ../available/sshd.conf
|
||||
| `- init.conf -- Bootstrap tasks and services
|
||||
:
|
||||
```
|
||||
|
||||
To facilitate the task of managing configurations, be it a service,
|
||||
task, run, or other stanza, the `initctl` tool has a a few built-in
|
||||
commands:
|
||||
|
||||
```
|
||||
list List all .conf in /etc/finit.d/
|
||||
enable <CONF> Enable .conf in /etc/finit.d/available/
|
||||
disable <CONF> Disable .conf in /etc/finit.d/[enabled/]
|
||||
reload Reload *.conf in /etc/finit.d/ (activates changes)
|
||||
```
|
||||
|
||||
To enable a service like `sshd.conf`, above, use
|
||||
|
||||
initctl enable sshd
|
||||
|
||||
The `.conf` suffix is not needed, `initctl` adds it implicitly if it is
|
||||
missing. The `disable` command works in a similar fashion.
|
||||
|
||||
Note, however, that `initctl` only operates on symlinks and it always
|
||||
requires the `available/` sub-directory. Any non-symlink in the parent
|
||||
directory, here `/etc/init.d/`, will be considered a system override by
|
||||
`initctl`.
|
||||
Notice how both the service directory and bootstrap configuration file now
|
||||
use the custom `/etc/init.d/` path specified at build time.
|
||||
|
||||
[1]: build.md#configure
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
Finit Features
|
||||
==============
|
||||
|
||||
This page highlights some of Finit's key features with examples and usage
|
||||
scenarios. For complete documentation, configuration syntax, and advanced
|
||||
options, see the [Configuration](config/index.md) section.
|
||||
|
||||
**Process Supervision**
|
||||
|
||||
Start, monitor and restart services should they fail.
|
||||
@@ -162,6 +166,28 @@ See the [Linux Capabilities](config/capabilities.md) section for detailed
|
||||
information, examples, and security best practices.
|
||||
|
||||
|
||||
**Supplementary Groups**
|
||||
|
||||
Finit supports supplementary groups for services, allowing them to access
|
||||
resources owned by multiple groups without running as root. This complements
|
||||
capabilities for fine-grained privilege control.
|
||||
|
||||
```conf
|
||||
service @caddy:caddy,ssl-cert /usr/bin/caddy run
|
||||
```
|
||||
|
||||
In this example, the Caddy web server runs as user `caddy` with primary group
|
||||
`caddy`, but also has access to resources owned by the `ssl-cert` group (such
|
||||
as TLS certificates).
|
||||
|
||||
Finit automatically reads the user's supplementary group membership from
|
||||
`/etc/group`. Additional groups can be specified explicitly using the syntax
|
||||
`@user:group,sup1,sup2,...`.
|
||||
|
||||
See the [Non-privileged Services](config/services.md#non-privileged-services)
|
||||
section for more information.
|
||||
|
||||
|
||||
**Cgroups**
|
||||
|
||||
Finit supports cgroups v2 and comes with the following default groups in
|
||||
@@ -207,4 +233,59 @@ commands for details.
|
||||
> disabled early at boot.
|
||||
|
||||
|
||||
**Service Management**
|
||||
|
||||
Finit includes the `initctl` tool for managing services and system state at
|
||||
runtime. Key capabilities include:
|
||||
|
||||
- **Enable/Disable services**: Manage which services start at boot by moving
|
||||
configuration files between `/etc/finit.d/available` and
|
||||
`/etc/finit.d/enabled`
|
||||
- **Start/Stop/Restart**: Control individual services without requiring a
|
||||
full system reboot
|
||||
- **Status monitoring**: View service state, PID, uptime, and resource usage
|
||||
- **Condition management**: Set and clear user-defined conditions to control
|
||||
service dependencies
|
||||
- **Cgroup monitoring**: Real-time process and resource monitoring with
|
||||
`initctl top`, similar to the traditional `top` command but cgroup-aware
|
||||
|
||||
Example commands:
|
||||
|
||||
```bash
|
||||
initctl enable myservice # Enable service for next boot
|
||||
initctl start myservice # Start service now
|
||||
initctl status # Show all services
|
||||
initctl top # Interactive resource monitor
|
||||
initctl cond set usr/custom # Set custom condition
|
||||
```
|
||||
|
||||
See the [Commands & Status](initctl.md) section for complete documentation.
|
||||
|
||||
|
||||
**Rescue Mode**
|
||||
|
||||
Finit provides a built-in rescue mode for system recovery and maintenance.
|
||||
When booting with the `rescue` kernel parameter, the system enters a
|
||||
protected maintenance shell.
|
||||
|
||||
If the bundled `sulogin` program is available (from Finit, util-linux, or
|
||||
BusyBox), you'll be prompted for the root password before accessing the
|
||||
maintenance shell. This provides secure access for system recovery.
|
||||
|
||||
If `sulogin` is not available, Finit falls back to reading
|
||||
`/lib/finit/rescue.conf` and boots the system in a limited maintenance mode.
|
||||
|
||||
```
|
||||
# Kernel command line
|
||||
linux /vmlinuz root=/dev/sda1 rescue
|
||||
```
|
||||
|
||||
In rescue mode, `initctl` will not work. After fixing the problem, use
|
||||
`reboot -f` to force reboot.
|
||||
|
||||
Rescue mode can be disabled at build time with `configure --without-rescue`.
|
||||
|
||||
See the [Rescue Mode](config/rescue.md) section for more information.
|
||||
|
||||
|
||||
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||
|
||||
+19
-14
@@ -1,7 +1,7 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
{ align=right }
|
||||
{ align=right width=40% }
|
||||
|
||||
> Reverse engineered from the [EeePC fastinit][]
|
||||
> "gaps filled with frog DNA …"
|
||||
@@ -17,26 +17,30 @@ PID file monitoring, or [conditions](conditions.md).
|
||||
Features
|
||||
--------
|
||||
|
||||
* [Runlevels][5], defined per service
|
||||
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
||||
* Runparts and `/etc/rc.local` support
|
||||
* [Runlevels](config/runlevels.md), defined per service
|
||||
* [One-shot tasks](config/task-and-run.md), [services](config/services.md) (daemons), or [SysV init][4] start/stop scripts
|
||||
* [Runparts](config/runparts.md) and `/etc/rc.local` support
|
||||
* Process supervision similar to [systemd][]
|
||||
* Sourcing environment files
|
||||
* Conditions for network/process/custom dependencies
|
||||
* Readiness notification; PID files (native) for synchronizing system
|
||||
* Fine-grained privilege control:
|
||||
- [Linux capabilities](config/capabilities.md) for minimal required privileges
|
||||
- [Supplementary groups](config/services.md#non-privileged-services) for multi-group resource access
|
||||
* [Sourcing environment files](config/service-env.md)
|
||||
* [Conditions](conditions.md) for network/process/custom dependencies
|
||||
* [Readiness notification](config/service-sync.md); PID files (native) for synchronizing system
|
||||
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
||||
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
||||
* Pre/Post script actions
|
||||
* [Pre/Post script actions](config/service-wrappers.md)
|
||||
* Rudimentary [templating support](config/templating.md)
|
||||
* Tooling to enable/disable services
|
||||
* Built-in getty
|
||||
* [Tooling](initctl.md) to enable/disable services
|
||||
* [Automatic reload](features.md#automatic-reload) of modified configuration files (optional)
|
||||
* [Built-in getty](config/tty.md)
|
||||
* Built-in watchdog, with support for hand-over to [watchdogd][]
|
||||
* Built-in support for Debian/BusyBox [`/etc/network/interfaces`][3]
|
||||
* Cgroups v2, both configuration and monitoring in `initctl top`
|
||||
* Plugin support for customization
|
||||
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
||||
* [Cgroups v2](config/cgroups.md), both configuration and monitoring in [`initctl top`](initctl.md)
|
||||
* [Plugin support](plugins.md) for customization
|
||||
* Proper [rescue mode](config/rescue.md) with bundled `sulogin` for protected maintenance shell
|
||||
* Integration with [watchdogd][] for full system supervision
|
||||
* Logging to kernel ring buffer before `syslogd` has started, see the
|
||||
* [Logging](config/logging.md) to kernel ring buffer before `syslogd` has started, see the
|
||||
recommended [sysklogd][] project for complete logging integration
|
||||
and how to log to the kernel ring buffer from scripts using `logger`
|
||||
|
||||
@@ -64,6 +68,7 @@ and proposed extensions.
|
||||
[4]: https://en.wikipedia.org/wiki/Init
|
||||
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||
[6]: https://github.com/finit-project/finit
|
||||
[dinit]: https://davmac.org/projects/dinit/
|
||||
[systemd]: https://www.freedesktop.org/wiki/Software/systemd/
|
||||
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||
[s6 style]: https://skarnet.org/software/s6/notifywhenup.html
|
||||
|
||||
+28
-21
@@ -1,6 +1,6 @@
|
||||
site_name: Documentation
|
||||
site_name: ""
|
||||
site_description: Fast Init for Linux Systems
|
||||
site_url: http://finit-project.github.io/finit/
|
||||
site_url: http://finit-project.github.io
|
||||
repo_url: https://github.com/finit-project/finit
|
||||
repo_name: Finit Project
|
||||
copyright: Copyright © 2008-2025 Joachim Wiberg
|
||||
@@ -11,6 +11,7 @@ extra_css:
|
||||
|
||||
exclude_docs: |
|
||||
TODO.md
|
||||
ChangeLog.md
|
||||
|
||||
theme:
|
||||
logo: img/logo.png
|
||||
@@ -22,7 +23,7 @@ theme:
|
||||
- navigation.instant
|
||||
- navigation.instant.progress
|
||||
- navigation.tracking
|
||||
# - navigation.tabs
|
||||
- navigation.tabs
|
||||
# - navigation.sections
|
||||
# - navigation.expand
|
||||
# - navigation.top
|
||||
@@ -49,20 +50,16 @@ theme:
|
||||
name: Switch to light mode
|
||||
|
||||
nav:
|
||||
- Introduction: index.md
|
||||
- Example: example.md
|
||||
- Features: features.md
|
||||
- Commands & Status: initctl.md
|
||||
- Rebooting & Halting: commands.md
|
||||
- Runlevels: runlevels.md
|
||||
- Runparts & /etc/rc.local: runparts.md
|
||||
- Getting Started:
|
||||
- Introduction: index.md
|
||||
- Features: features.md
|
||||
- Quick Example: example.md
|
||||
- Building: build.md
|
||||
- Configuration:
|
||||
- Overview: config/index.md
|
||||
- Files & Layout: config/files.md
|
||||
- Conditions: conditions.md
|
||||
- Cgroups: config/cgroups.md
|
||||
- Capabilities: config/capabilities.md
|
||||
- Environment Variables: config/env.md
|
||||
- Runlevels: config/runlevels.md
|
||||
- One-shot Tasks: config/task-and-run.md
|
||||
- Services:
|
||||
- Syntax: config/services.md
|
||||
@@ -71,24 +68,29 @@ nav:
|
||||
- Synchronization: config/service-sync.md
|
||||
- Wrapper Scripts: config/service-wrappers.md
|
||||
- Run-parts Scripts: config/runparts.md
|
||||
- Runlevels: config/runlevels.md
|
||||
- TTY & Console: config/tty.md
|
||||
- Templating: config/templating.md
|
||||
- Environment Variables: config/env.md
|
||||
- Logging: config/logging.md
|
||||
- Cgroups: config/cgroups.md
|
||||
- Capabilities: config/capabilities.md
|
||||
- Templating: config/templating.md
|
||||
- SysV Compatibility: config/sysv.md
|
||||
- Rescue Mode: config/rescue.md
|
||||
- Limitations: config/limitations.md
|
||||
- Usage:
|
||||
- Building: build.md
|
||||
- Command Line: cmdline.md
|
||||
- Plugins: plugins.md
|
||||
- Services: service.md
|
||||
- Commands & Status: initctl.md
|
||||
- Rebooting & Halting: commands.md
|
||||
- Command Line Options: cmdline.md
|
||||
- Managing Services: service.md
|
||||
- Signals: signals.md
|
||||
- Reference:
|
||||
- Distributions: distro.md
|
||||
- keventd: keventd.md
|
||||
- Runlevels Overview: runlevels.md
|
||||
- Runparts & rc.local: runparts.md
|
||||
- Plugins: plugins.md
|
||||
- Watchdog: watchdog.md
|
||||
- keventd: keventd.md
|
||||
- Service State Machine: state-machine.md
|
||||
- Distributions: distro.md
|
||||
- Requirements: requirements.md
|
||||
|
||||
markdown_extensions:
|
||||
@@ -109,6 +111,11 @@ markdown_extensions:
|
||||
plugins:
|
||||
- search
|
||||
- callouts
|
||||
- glightbox
|
||||
|
||||
extra:
|
||||
homepage: https://finit-project.github.io/
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/finit-project/finit
|
||||
name: Finit on GitHub
|
||||
|
||||
+4
-9
@@ -37,7 +37,7 @@
|
||||
|
||||
#define CDIM plain ? "" : "\e[2m"
|
||||
#define CRST plain ? "" : "\e[0m"
|
||||
#define CLREOL plain ? "" : "\e[K" /* Clear to end of line */
|
||||
#define CLREOL plain ? "" : "\e[K" /* Clear to end of line */
|
||||
|
||||
#define NONE " "
|
||||
#define PIPE plain ? "| " : "│ "
|
||||
@@ -630,14 +630,9 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
||||
strlcat(row, ++i == num ? END : FORK, rlen);
|
||||
|
||||
snprintf(proc, sizeof(proc), " %d %s", pid, cmdline);
|
||||
|
||||
if (plain) {
|
||||
strlcat(row, proc, rlen);
|
||||
} else {
|
||||
strlcat(row, CDIM, rlen);
|
||||
strlcat(row, proc, rlen);
|
||||
strlcat(row, CRST, sizeof(row));
|
||||
}
|
||||
strlcat(row, CDIM, rlen);
|
||||
strlcat(row, proc, rlen);
|
||||
strlcat(row, CRST, sizeof(row));
|
||||
|
||||
printf("\r%s%s\n", row, CLREOL);
|
||||
pos++;
|
||||
|
||||
@@ -286,6 +286,12 @@ static void prepare_tty(char *tty, speed_t speed, const char *procname, struct r
|
||||
char name[80];
|
||||
int fd, dummy;
|
||||
|
||||
/* Set proper protections and ownership */
|
||||
if (chown(tty, 0, 0))
|
||||
logit(LOG_ERR, "failed chowning 0:0 %s: %s", tty, strerror(errno));
|
||||
if (chmod(tty, 0620))
|
||||
logit(LOG_ERR, "failed chmoding 620 %s: %s", tty, strerror(errno));
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0) {
|
||||
logit(LOG_ERR, "Failed opening %s: %s", tty, strerror(errno));
|
||||
|
||||
+17
-5
@@ -39,6 +39,7 @@
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
#include <sys/prctl.h>
|
||||
#include <paths.h>
|
||||
#ifdef _LIBITE_LITE
|
||||
# include <libite/lite.h>
|
||||
#else
|
||||
@@ -60,8 +61,9 @@
|
||||
#include "util.h"
|
||||
#include "utmp-api.h"
|
||||
|
||||
uev_ctx_t *ctx = NULL; /* Main loop context */
|
||||
svc_t *wdog = NULL; /* No watchdog by default */
|
||||
uev_ctx_t *ctx; /* Main loop context */
|
||||
svc_t *wdog; /* No watchdog by default */
|
||||
char *arg0; /* Saved for setprocnm() */
|
||||
|
||||
|
||||
/*
|
||||
@@ -371,7 +373,6 @@ static void fs_finalize(void)
|
||||
/* Modern systems use /dev/pts */
|
||||
if (!fismnt("/dev/pts")) {
|
||||
char opts[32];
|
||||
int mode;
|
||||
int gid;
|
||||
|
||||
gid = getgroup("tty");
|
||||
@@ -379,8 +380,7 @@ static void fs_finalize(void)
|
||||
gid = 0;
|
||||
|
||||
/* 0600 is default on Debian, use 0620 to get mesg y by default */
|
||||
mode = 0620;
|
||||
snprintf(opts, sizeof(opts), "gid=%d,mode=%d,ptmxmode=0666", gid, mode);
|
||||
snprintf(opts, sizeof(opts), "gid=%d,mode=0620,ptmxmode=0666", gid);
|
||||
|
||||
makedir("/dev/pts", 0755);
|
||||
fs_mount("devpts", "/dev/pts", "devpts", flags, opts);
|
||||
@@ -610,6 +610,9 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
uev_ctx_t loop;
|
||||
|
||||
/* Save argv for setprocnm() in child processes */
|
||||
arg0 = argv[0];
|
||||
|
||||
/* user calling telinit or init */
|
||||
if (getpid() != 1) {
|
||||
if (geteuid() == 0)
|
||||
@@ -624,6 +627,15 @@ int main(int argc, char *argv[])
|
||||
return EX_NOPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check critical environment variables. We need PATH
|
||||
* and SHELL for early commands like mount in fs_init().
|
||||
*/
|
||||
if (!checkenv("PATH"))
|
||||
setenv("PATH", _PATH_STDPATH, 1);
|
||||
if (!checkenv("SHELL"))
|
||||
setenv("SHELL", _PATH_BSHELL, 1);
|
||||
|
||||
/*
|
||||
* Need /dev, /proc, and /sys for console=, remount and cgroups
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <sysexits.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/prctl.h>
|
||||
#ifdef _LIBITE_LITE
|
||||
# include <libite/lite.h>
|
||||
#else
|
||||
@@ -527,6 +528,29 @@ int in_container(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* setprocnm - Set process name in argv[0] for ps/pidof
|
||||
* @name: New process name to set
|
||||
*
|
||||
* Changes the process name by modifying argv[0]. This is particularly
|
||||
* useful for compatibility with BusyBox's pidof which reads cmdline
|
||||
* from /proc/pid/cmdline rather than /proc/pid/comm.
|
||||
*/
|
||||
void setprocnm(const char *name)
|
||||
{
|
||||
extern char *arg0;
|
||||
size_t len;
|
||||
|
||||
if (!arg0 || !name)
|
||||
return;
|
||||
|
||||
prctl(PR_SET_NAME, name, 0, 0, 0);
|
||||
|
||||
len = strlen(arg0);
|
||||
memset(arg0, 0, len);
|
||||
strlcpy(arg0, name, len + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
|
||||
@@ -72,6 +72,7 @@ int print_result (int fail);
|
||||
void set_hostname (char **hostname);
|
||||
void networking (int updown);
|
||||
int in_container (void);
|
||||
void setprocnm (const char *name);
|
||||
|
||||
int complete (char *cmd, int pid);
|
||||
int run (char *cmd, char *log);
|
||||
@@ -82,6 +83,17 @@ pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimi
|
||||
pid_t run_bg (char *cmd, char *args[]);
|
||||
int run_parts (char *dir, char *cmd, const char *env[], int progress, int sysv);
|
||||
|
||||
|
||||
static inline int checkenv(const char *env)
|
||||
{
|
||||
const char *val = getenv(env);
|
||||
|
||||
if (!val || !val[0])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int dprint(int fd, const char *s, size_t len)
|
||||
{
|
||||
size_t loop = 3;
|
||||
|
||||
+137
-11
@@ -25,6 +25,7 @@
|
||||
#include "config.h" /* Generated by configure script */
|
||||
|
||||
#include <ctype.h> /* isblank() */
|
||||
#include <grp.h> /* setgroups() */
|
||||
#include <sched.h> /* sched_yield() */
|
||||
#include <string.h>
|
||||
#include <sys/reboot.h>
|
||||
@@ -495,14 +496,21 @@ static void compose_cmdline(svc_t *svc, char *buf, size_t len)
|
||||
static void set_uid(uid_t uid, svc_t *svc)
|
||||
{
|
||||
#ifdef HAVE_LIBCAP
|
||||
if (cap_setuid(uid)) {
|
||||
err(1, "%s: failed cap_setuid(%d)", svc_ident(svc, NULL, 0), uid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* After dropping privileges, set the specific capabilities we need */
|
||||
/*
|
||||
* Only use cap_setuid() if capabilities are configured,
|
||||
* otherwise it would (by design) drop all capabilities,
|
||||
* breaking root services
|
||||
*/
|
||||
if (svc->capabilities[0]) {
|
||||
cap_iab_t cap_iab = cap_iab_from_text(svc->capabilities);
|
||||
cap_iab_t cap_iab;
|
||||
|
||||
if (cap_setuid(uid)) {
|
||||
err(1, "%s: failed cap_setuid(%d)", svc_ident(svc, NULL, 0), uid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* After dropping privileges, set the specific capabilities we need */
|
||||
cap_iab = cap_iab_from_text(svc->capabilities);
|
||||
if (!cap_iab) {
|
||||
err(1, "%s: failed parsing capabilities '%s'",
|
||||
svc_ident(svc, NULL, 0), svc->capabilities);
|
||||
@@ -515,11 +523,10 @@ static void set_uid(uid_t uid, svc_t *svc)
|
||||
svc_ident(svc, NULL, 0));
|
||||
}
|
||||
cap_free(cap_iab);
|
||||
}
|
||||
#else
|
||||
} else
|
||||
#endif
|
||||
if (setuid(uid))
|
||||
err(1, "%s: failed setuid(%d)", svc_ident(svc, NULL, 0), uid);
|
||||
#endif
|
||||
}
|
||||
|
||||
static pid_t service_fork(svc_t *svc)
|
||||
@@ -549,7 +556,21 @@ static pid_t service_fork(svc_t *svc)
|
||||
#else
|
||||
int uid = getuser(svc->username, &home);
|
||||
int gid = getgroup(svc->group);
|
||||
|
||||
/* Check for invalid user/group - fail rather than silent fallback */
|
||||
if (uid < 0) {
|
||||
err(1, "%s: user '%s' not found, cannot start service",
|
||||
svc_ident(svc, NULL, 0), svc->username);
|
||||
return -1;
|
||||
}
|
||||
if (gid < 0) {
|
||||
err(1, "%s: group '%s' not found, cannot start service",
|
||||
svc_ident(svc, NULL, 0), svc->group);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (svc_is_tty(svc))
|
||||
setprocnm("getty");
|
||||
|
||||
sched_yield();
|
||||
|
||||
@@ -560,6 +581,42 @@ static pid_t service_fork(svc_t *svc)
|
||||
svc_ident(svc, NULL, 0), rlim2str(i));
|
||||
}
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
/* Set supplementary groups from /etc/group and config */
|
||||
{
|
||||
gid_t supgids[NGROUPS_MAX];
|
||||
int ngroups = NGROUPS_MAX;
|
||||
int i, j, n = 0;
|
||||
|
||||
/* Get user's supplementary groups from /etc/group */
|
||||
if (getgrouplist(svc->username, gid, supgids, &ngroups) >= 0)
|
||||
n = ngroups;
|
||||
|
||||
/* Add explicitly configured supplementary groups */
|
||||
for (i = 0; i < svc->num_supgroups && n < NGROUPS_MAX; i++) {
|
||||
int g = getgroup(svc->supgroups[i]);
|
||||
int found = 0;
|
||||
|
||||
if (g < 0) {
|
||||
warn("%s: unknown supplementary group '%s'",
|
||||
svc_ident(svc, NULL, 0), svc->supgroups[i]);
|
||||
continue;
|
||||
}
|
||||
/* Skip if already in list from /etc/group */
|
||||
for (j = 0; j < n; j++) {
|
||||
if (supgids[j] == (gid_t)g) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
supgids[n++] = g;
|
||||
}
|
||||
if (n > 0 && setgroups(n, supgids))
|
||||
err(1, "%s: failed setgroups()", svc_ident(svc, NULL, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set desired user+group */
|
||||
if (gid >= 0) {
|
||||
if (setgid(gid))
|
||||
@@ -1384,6 +1441,26 @@ static void parse_env(svc_t *svc, char *env)
|
||||
strlcpy(svc->env, env, sizeof(svc->env));
|
||||
}
|
||||
|
||||
static void parse_caps(svc_t *svc, char *caps)
|
||||
{
|
||||
#ifdef HAVE_LIBCAP
|
||||
cap_iab_t cap_iab;
|
||||
|
||||
cap_iab = cap_iab_from_text(caps);
|
||||
if (!cap_iab) {
|
||||
err(1, "%s: failed parsing capabilities '%s'", svc_ident(svc, NULL, 0), caps);
|
||||
memset(svc->capabilities, 0, sizeof(svc->capabilities));
|
||||
return;
|
||||
}
|
||||
|
||||
cap_free(cap_iab);
|
||||
strlcpy(svc->capabilities, caps, sizeof(svc->capabilities));
|
||||
#else
|
||||
(void)svc;
|
||||
(void)caps;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* the @cgroup argument can be, e.g., .system,mem.max:1234 or just the
|
||||
* default group with some cfg, e.g., :mem.max:1234 as a side effect,
|
||||
@@ -1957,7 +2034,29 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
char *ptr = strchr(username, ':');
|
||||
|
||||
if (ptr) {
|
||||
char *sup;
|
||||
|
||||
*ptr++ = 0;
|
||||
/* Check for supplementary groups: group,sup1,sup2,... */
|
||||
sup = strchr(ptr, ',');
|
||||
if (sup) {
|
||||
*sup++ = 0;
|
||||
svc->num_supgroups = 0;
|
||||
while (sup) {
|
||||
char *next = strchr(sup, ',');
|
||||
if (next)
|
||||
*next++ = 0;
|
||||
if (svc->num_supgroups >= MAX_NUM_SUPGROUPS) {
|
||||
warn("%s: too many supplementary groups, max %d",
|
||||
svc->cmd, MAX_NUM_SUPGROUPS);
|
||||
break;
|
||||
}
|
||||
strlcpy(svc->supgroups[svc->num_supgroups], sup,
|
||||
sizeof(svc->supgroups[0]));
|
||||
svc->num_supgroups++;
|
||||
sup = next;
|
||||
}
|
||||
}
|
||||
strlcpy(svc->group, ptr, sizeof(svc->group));
|
||||
}
|
||||
strlcpy(svc->username, username, sizeof(svc->username));
|
||||
@@ -2052,7 +2151,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
else
|
||||
memset(svc->env, 0, sizeof(svc->env));
|
||||
if (caps)
|
||||
strlcpy(svc->capabilities, caps, sizeof(svc->capabilities));
|
||||
parse_caps(svc, caps);
|
||||
else
|
||||
memset(svc->capabilities, 0, sizeof(svc->capabilities));
|
||||
if (file)
|
||||
@@ -2529,6 +2628,7 @@ static void service_cleanup_script(svc_t *svc)
|
||||
static void service_retry(svc_t *svc)
|
||||
{
|
||||
char *restart_cnt = (char *)&svc->restart_cnt;
|
||||
int rc = WEXITSTATUS(svc->status);
|
||||
int timeout;
|
||||
|
||||
service_timeout_cancel(svc);
|
||||
@@ -2537,6 +2637,18 @@ static void service_retry(svc_t *svc)
|
||||
return;
|
||||
|
||||
if (svc->respawn) {
|
||||
/*
|
||||
* Non-zero exit indicates an error that may not be resolved
|
||||
* by immediate retry. Add delay to prevent busy-loop and to
|
||||
* rate-limit retries, e.g. when TTY device doesn't exist.
|
||||
*/
|
||||
if (WIFEXITED(svc->status) && rc != 0) {
|
||||
dbg("%s exited with error %d, delaying respawn ...",
|
||||
svc_ident(svc, NULL, 0), rc);
|
||||
service_timeout_after(svc, svc->restart_tmo, service_retry);
|
||||
return;
|
||||
}
|
||||
|
||||
dbg("%s crashed/exited, respawning ...", svc_ident(svc, NULL, 0));
|
||||
svc_unblock(svc);
|
||||
service_step(svc);
|
||||
@@ -2899,6 +3011,8 @@ restart:
|
||||
|
||||
if (!svc->pid) {
|
||||
if (svc_is_daemon(svc) || svc_is_tty(svc)) {
|
||||
int rc = WEXITSTATUS(svc->status);
|
||||
|
||||
svc_restarting(svc); /* BLOCK_RESTARTING */
|
||||
svc_set_state(svc, SVC_HALTED_STATE);
|
||||
|
||||
@@ -2913,6 +3027,18 @@ restart:
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-zero exit for respawn services (TTYs): delay retry
|
||||
* to prevent busy-loop and rate-limit retries
|
||||
*/
|
||||
if (WIFEXITED(svc->status) &&
|
||||
rc != 0) {
|
||||
dbg("%s exited with error %d, delaying respawn ...",
|
||||
svc_ident(svc, NULL, 0), rc);
|
||||
service_timeout_after(svc, svc->restart_tmo, service_retry);
|
||||
goto done;
|
||||
}
|
||||
|
||||
dbg("respawning %s", svc_ident(svc, NULL, 0));
|
||||
svc_unblock(svc);
|
||||
break;
|
||||
|
||||
@@ -362,7 +362,7 @@ restart:
|
||||
/* Restore terse mode and run hooks before shutdown */
|
||||
if (runlevel == 0 || runlevel == 6) {
|
||||
/* Hide cursor, we're going down ... */
|
||||
dprint(STDOUT_FILENO, "\033[?25l", 14);
|
||||
dprint(STDOUT_FILENO, "\033[?25l", 6);
|
||||
|
||||
api_exit();
|
||||
log_exit();
|
||||
|
||||
@@ -101,6 +101,7 @@ typedef enum {
|
||||
#define MAX_STR_LEN 64
|
||||
#define MAX_COND_LEN (MAX_ARG_LEN * 3)
|
||||
#define MAX_USER_LEN 16
|
||||
#define MAX_NUM_SUPGROUPS 4
|
||||
#define MAX_NUM_FDS 64 /* Max number of I/O plugins */
|
||||
#define MAX_NUM_SVC_ARGS 64
|
||||
|
||||
@@ -191,6 +192,8 @@ typedef struct svc {
|
||||
/* Identity */
|
||||
char username[MAX_USER_LEN];
|
||||
char group[MAX_USER_LEN];
|
||||
char supgroups[MAX_NUM_SUPGROUPS][MAX_USER_LEN];
|
||||
int num_supgroups;
|
||||
char capabilities[MAX_CMD_LEN];
|
||||
|
||||
/* Command, arguments and service description */
|
||||
|
||||
+38
-4
@@ -180,16 +180,34 @@ char *str(char *fmt, ...)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return UID for the given user, with fallback to 'root' if user is unset.
|
||||
* Fails with -1 only if user (incl. fallback) does not exist.
|
||||
*/
|
||||
int getuser(const char *username, char **home)
|
||||
{
|
||||
#ifdef ENABLE_STATIC
|
||||
if (!username || !username[0])
|
||||
username = "root";
|
||||
|
||||
if (home)
|
||||
*home = "/"; /* XXX: Fixme */
|
||||
return fgetint("/etc/passwd", "x:\n", username);
|
||||
#else
|
||||
struct passwd *usr;
|
||||
const struct passwd *usr;
|
||||
|
||||
if (!username || (usr = getpwnam(username)) == NULL)
|
||||
if (!username || !username[0]) {
|
||||
usr = getpwuid(0);
|
||||
if (!usr)
|
||||
return -1;
|
||||
|
||||
if (home)
|
||||
*home = usr->pw_dir;
|
||||
return usr->pw_uid;
|
||||
}
|
||||
|
||||
usr = getpwnam(username);
|
||||
if (!usr)
|
||||
return -1;
|
||||
|
||||
if (home)
|
||||
@@ -198,14 +216,30 @@ int getuser(const char *username, char **home)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return GID for the given group, with fallback to 'root' if group is unset.
|
||||
* Fails with -1 only if user (incl. fallback) does not exist.
|
||||
*/
|
||||
int getgroup(const char *group)
|
||||
{
|
||||
#ifdef ENABLE_STATIC
|
||||
if (!group || !group[0])
|
||||
group = "root";
|
||||
|
||||
return fgetint("/etc/group", "x:\n", group);
|
||||
#else
|
||||
struct group *grp;
|
||||
const struct group *grp;
|
||||
|
||||
if ((grp = getgrnam(group)) == NULL)
|
||||
if (!group || !group[0]) {
|
||||
grp = getgrgid(0);
|
||||
if (!grp)
|
||||
return -1;
|
||||
|
||||
return grp->gr_gid;
|
||||
}
|
||||
|
||||
grp = getgrnam(group);
|
||||
if (!grp)
|
||||
return -1;
|
||||
|
||||
return grp->gr_gid;
|
||||
|
||||
@@ -10,6 +10,7 @@ EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env
|
||||
skel/etc/rcS.d/S01abc.sh skel/etc/rcS.d/S02def.sh \
|
||||
skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
|
||||
skel/etc/inittab skel/etc/hostname skel/etc/fstab \
|
||||
skel/etc/passwd skel/etc/group skel/etc/ld.so.conf \
|
||||
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \
|
||||
skel/etc/finit.d/.empty skel/etc/finit.d/available/.empty \
|
||||
skel/etc/finit.d/enabled/.empty \
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
set -eu
|
||||
|
||||
echo "=== Finit Test Sysroot Setup ==="
|
||||
echo "Date: $(date)"
|
||||
echo "SYSROOT: $SYSROOT"
|
||||
echo "top_builddir: $top_builddir"
|
||||
echo "srcdir: $srcdir"
|
||||
echo "================================"
|
||||
echo
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
make -C "$top_builddir" DESTDIR="$SYSROOT" install
|
||||
|
||||
@@ -21,3 +29,13 @@ done
|
||||
for conf in 10-hotplug.conf; do
|
||||
find "$SYSROOT" -name $conf -delete
|
||||
done
|
||||
|
||||
# Update dynamic linker cache for /usr/local/lib libraries
|
||||
echo "Running ldconfig in sysroot: $SYSROOT"
|
||||
echo "Contents of $SYSROOT/etc/ld.so.conf:"
|
||||
cat "$SYSROOT/etc/ld.so.conf" || echo "Warning: ld.so.conf not found"
|
||||
echo "Libraries in $SYSROOT/usr/local/lib:"
|
||||
ls -la "$SYSROOT/usr/local/lib/" 2>/dev/null || echo "Warning: /usr/local/lib not found in sysroot"
|
||||
ldconfig -v -r "$SYSROOT" || echo "Warning: ldconfig failed with exit code $?"
|
||||
echo "Verifying ldconfig cache was created:"
|
||||
ls -la "$SYSROOT/etc/ld.so.cache" || echo "Warning: ld.so.cache not created"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
root:x:0:
|
||||
daemon:x:1:
|
||||
bin:x:2:
|
||||
sys:x:3:
|
||||
adm:x:4:
|
||||
tty:x:5:
|
||||
disk:x:6:
|
||||
dialout:x:20:
|
||||
nogroup:x:65534:
|
||||
@@ -0,0 +1,3 @@
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
/lib
|
||||
@@ -0,0 +1,5 @@
|
||||
root:x:0:0:root:/root:/bin/sh
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
Reference in New Issue
Block a user