summaryrefslogtreecommitdiff
path: root/Userland/Utilities
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-21 09:58:31 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-21 11:08:20 +0100
commit77e0598c6d5ab732cf43297f629867f01da08833 (patch)
tree25c2f625fbbd36e80e8f7aaefc8242410941a8c0 /Userland/Utilities
parentc9a7f81dc33692da3a079a202862c502cd1de1d0 (diff)
downloadserenity-77e0598c6d5ab732cf43297f629867f01da08833.zip
passwd+LibCore: Make passwd replace /etc files atomically
Before this patch, we had a nasty race condition when changing a user's password: there was a time window between truncating /etc/shadow and writing out its new contents, where you could simply "su" to root without using a password. Instead of writing directly to /etc/passwd and /etc/shadow, we now create temporary files in /etc and fill them with the new contents. Those files are then atomically renamed to /etc/passwd and /etc/shadow. Sadly, fixing this race requires giving the passwd program a lot more privileges. This is something we can and should improve upon. :^)
Diffstat (limited to 'Userland/Utilities')
-rw-r--r--Userland/Utilities/passwd.cpp34
1 files changed, 8 insertions, 26 deletions
diff --git a/Userland/Utilities/passwd.cpp b/Userland/Utilities/passwd.cpp
index b0a36e437a..62c8b321a4 100644
--- a/Userland/Utilities/passwd.cpp
+++ b/Userland/Utilities/passwd.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, Peter Elliott <pelliott@ualberta.ca>
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,22 +40,17 @@ int main(int argc, char** argv)
return 1;
}
- if (pledge("stdio wpath rpath cpath tty id", nullptr) < 0) {
- perror("pledge");
+ if (setegid(0) < 0) {
+ perror("setegid");
return 1;
}
- if (unveil("/etc/passwd", "rwc") < 0) {
- perror("unveil");
- return 1;
- }
-
- if (unveil("/etc/group", "rwc") < 0) {
- perror("unveil");
+ if (pledge("stdio wpath rpath wpath cpath fattr tty", nullptr) < 0) {
+ perror("pledge");
return 1;
}
- if (unveil("/etc/shadow", "rwc") < 0) {
+ if (unveil("/etc", "rwc") < 0) {
perror("unveil");
return 1;
}
@@ -86,23 +82,9 @@ int main(int argc, char** argv)
return 1;
}
- // Drop privileges after opening all the files through the Core::Account object.
- auto gid = getgid();
- if (setresgid(gid, gid, gid) < 0) {
- perror("setresgid");
- return 1;
- }
-
- auto uid = getuid();
- if (setresuid(uid, uid, uid) < 0) {
- perror("setresuid");
- return 1;
- }
-
- // Make sure /etc/passwd is open and ready for reading, then we can drop a bunch of pledge promises.
setpwent();
- if (pledge("stdio tty", nullptr) < 0) {
+ if (pledge("stdio rpath wpath cpath fattr tty", nullptr) < 0) {
perror("pledge");
return 1;
}
@@ -131,7 +113,7 @@ int main(int argc, char** argv)
target_account.set_password(new_password.value().characters());
}
- if (pledge("stdio", nullptr) < 0) {
+ if (pledge("stdio rpath wpath cpath fattr", nullptr) < 0) {
perror("pledge");
return 1;
}