feat: login rate limiting, network drivers in initfs

P2-2: Login rate limiting (userutils/login.rs):
- Tracks consecutive failures, resets on success
- 3+ failures: exponential delay up to 30 seconds
- Applies to both password and blank-password login paths

P2-3: Network stack in initfs (base-initfs + service files):
- Added e1000d, rtl8168d to base-initfs BINS
- 60_smolnetd.service: network stack in initfs
- 61_dhcpd.service: DHCP client in initfs
- Network available before switch_root

Part of COMPREHENSIVE-FIX-AND-IMPROVEMENT-PLAN Phases P2.
This commit is contained in:
2026-05-03 09:50:59 +01:00
parent 2e313860f0
commit 8237bc45e8
7 changed files with 73 additions and 4 deletions
@@ -0,0 +1,24 @@
--- a/init.initfs.d/60_smolnetd.service 1970-01-01 00:00:00.000000000 +0000
+++ b/init.initfs.d/60_smolnetd.service 2026-05-03 09:49:05.837127632 +0100
@@ -0,0 +1,7 @@
+[unit]
+description = "Network Stack"
+requires_weak = ["40_drivers.target"]
+
+[service]
+cmd = "smolnetd"
+type = "notify"
--- a/init.initfs.d/61_dhcpd.service 1970-01-01 00:00:00.000000000 +0000
+++ b/init.initfs.d/61_dhcpd.service 2026-05-03 09:49:05.837757425 +0100
@@ -0,0 +1,7 @@
+[unit]
+description = "DHCP Client"
+requires_weak = ["60_smolnetd.service"]
+
+[service]
+cmd = "dhcpd"
+type = "oneshot_async"
--- a/init.initfs.d/.gitkeep 2026-05-03 09:49:05.835495601 +0100
+++ b/init.initfs.d/.gitkeep 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-
@@ -0,0 +1,43 @@
--- a/src/bin/login.rs 2026-05-03 09:46:36.866954421 +0100
+++ /mnt/data/homes/kellito/Builds/rbos/b/src/bin/login.rs 2026-05-03 09:46:36.867061170 +0100
@@ -120,6 +120,7 @@
pub fn main() {
let mut stdout = io::stdout();
let mut stderr = io::stderr();
+ let mut consecutive_failures: u32 = 0;
let _args = clap_app!(login =>
(author: "Jeremy Soller, Jose Narvaez")
@@ -133,6 +134,10 @@
}
loop {
+ if consecutive_failures >= 3 {
+ let delay_secs = std::cmp::min(consecutive_failures as u64, 30);
+ std::thread::sleep(std::time::Duration::from_secs(delay_secs));
+ }
let user = liner::Context::new()
.read_line(
liner::Prompt::from("\x1B[1mredox login:\x1B[0m "),
@@ -150,11 +155,13 @@
None => {
stdout.write(b"\nLogin incorrect\n").r#try(&mut stderr);
stdout.write(b"\n").r#try(&mut stderr);
+ consecutive_failures += 1;
stdout.flush().r#try(&mut stderr);
continue;
}
Some(user) => {
if user.is_passwd_blank() {
+ consecutive_failures = 0;
if let Ok(mut motd) = File::open(MOTD_FILE) {
io::copy(&mut motd, &mut stdout).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
@@ -185,6 +192,7 @@
stdout.flush().r#try(&mut stderr);
if user.verify_passwd(&password) {
+ consecutive_failures = 0;
if let Ok(mut motd) = File::open(MOTD_FILE) {
io::copy(&mut motd, &mut stdout).r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);