1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! linprov: eBPF mark-of-the-web for Linux.
//!
//! `linprov run` is the daemon; `linprov setup` is the first-time
//! install helper; `linprov upgrade` restarts the systemd unit after
//! a fresh `cargo install --force linprov`. See README and
//! CONTRIBUTING for the bigger picture.
use anyhow::Result;
use clap::{Parser, Subcommand};
mod allow;
mod allowlist;
mod config;
mod control;
mod encoding;
mod handler;
mod hashdb;
mod inode_storage;
mod install;
mod key;
mod mode;
mod notify;
mod privilege;
mod run;
mod setup;
mod upgrade;
pub(crate) use mode::Mode as ModeArg;
#[derive(Parser, Debug)]
#[command(
name = "linprov",
version,
about = "eBPF-based mark-of-the-web for Linux",
arg_required_else_help = true
)]
struct Cli {
#[command(subcommand)]
command: Cmd,
}
#[derive(Subcommand, Debug)]
enum Cmd {
/// Run the daemon (used by the systemd unit).
Run(run::RunArgs),
/// First-time install: feature-check the host, write a default
/// config + empty allowlist, drop a systemd unit. On a TTY it then
/// walks you through soak/enforce and optionally sets up the desktop
/// tray UI; `--yes` keeps it non-interactive.
Setup(setup::SetupArgs),
/// After `cargo install --force linprov` lays down a new binary,
/// reload systemd and restart linprov.service.
Upgrade(upgrade::UpgradeArgs),
/// Permit a blocked exec by the token from its `BLOCKED-EXEC` /
/// `BLOCKED-SCRIPT` log line. Talks to the running daemon's control
/// socket; `--once` applies it in memory only (not persisted).
Allow(allow::AllowArgs),
/// User-session tray agent: subscribe to blocks over the control
/// socket and surface Allow once / Allow always / Close in a tray
/// menu. Run from your graphical session (e.g. sway `exec`).
Notify(notify::NotifyArgs),
}
fn main() -> Result<()> {
// `run` initializes its own logger from the resolved config; the
// other subcommands get a simple stderr logger so we see the
// setup / upgrade progress messages.
let cli = Cli::parse();
if !matches!(cli.command, Cmd::Run(_)) {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
}
match cli.command {
Cmd::Run(args) => run::execute(args),
Cmd::Setup(args) => setup::run(args),
Cmd::Upgrade(args) => upgrade::run(args),
Cmd::Allow(args) => allow::run(args),
Cmd::Notify(args) => notify::run(args),
}
}