mirror of
https://github.com/aristocratos/btop.git
synced 2024-05-21 04:43:36 +12:00
Fixed: Security issue when running with SUID bit set
This commit is contained in:
parent
98ae5e8f46
commit
0f566ae688
27
src/btop.cpp
27
src/btop.cpp
|
@ -64,6 +64,7 @@ namespace Global {
|
|||
string fg_green = "\x1b[1;92m";
|
||||
string fg_red = "\x1b[0;91m";
|
||||
|
||||
uid_t real_uid, set_uid;
|
||||
|
||||
fs::path self_path;
|
||||
|
||||
|
@ -298,6 +299,18 @@ namespace Runner {
|
|||
~thread_lock() { if (status == 0) pthread_mutex_unlock(&pt_mutex); }
|
||||
};
|
||||
|
||||
//* Wrapper for raising priviliges when using SUID bit
|
||||
class gain_priv {
|
||||
int status = -1;
|
||||
public:
|
||||
gain_priv() {
|
||||
if (Global::real_uid != Global::set_uid) this->status = seteuid(Global::set_uid);
|
||||
}
|
||||
~gain_priv() {
|
||||
if (status == 0) status = seteuid(Global::real_uid);
|
||||
}
|
||||
};
|
||||
|
||||
string output;
|
||||
string empty_bg;
|
||||
bool pause_output = false;
|
||||
|
@ -385,6 +398,9 @@ namespace Runner {
|
|||
//? Atomic lock used for blocking non thread-safe actions in main thread
|
||||
atomic_lock lck(active);
|
||||
|
||||
//? Set effective user if SUID bit is set
|
||||
gain_priv powers{};
|
||||
|
||||
auto& conf = current_conf;
|
||||
|
||||
//! DEBUG stats
|
||||
|
@ -616,6 +632,17 @@ int main(int argc, char **argv) {
|
|||
|
||||
Global::start_time = time_s();
|
||||
|
||||
//? Save real and effective userid's and drop priviliges until needed if running with SUID bit set
|
||||
Global::real_uid = getuid();
|
||||
Global::set_uid = geteuid();
|
||||
if (Global::real_uid != Global::set_uid) {
|
||||
if (seteuid(Global::real_uid) != 0) {
|
||||
Global::real_uid = Global::set_uid;
|
||||
Global::exit_error_msg = "Failed to change effective user ID. Unset btop SUID bit to ensure security on this system. Quitting!";
|
||||
clean_quit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//? Call argument parser if launched with arguments
|
||||
if (argc > 1) argumentParser(argc, argv);
|
||||
|
||||
|
|
|
@ -589,6 +589,7 @@ namespace Config {
|
|||
void write() {
|
||||
if (conf_file.empty() or not write_new) return;
|
||||
Logger::debug("Writing new config file");
|
||||
if (geteuid() != Global::real_uid and seteuid(Global::real_uid) != 0) return;
|
||||
std::ofstream cwrite(conf_file, std::ios::trunc);
|
||||
if (cwrite.good()) {
|
||||
cwrite << "#? Config file for btop v. " << Global::Version;
|
||||
|
|
|
@ -27,6 +27,7 @@ tab-size = 4
|
|||
#include <array>
|
||||
#include <ifaddrs.h>
|
||||
#include <tuple>
|
||||
#include <unistd.h>
|
||||
|
||||
using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std::atomic, std::array, std::tuple;
|
||||
|
||||
|
@ -43,6 +44,7 @@ namespace Global {
|
|||
extern atomic<bool> resized;
|
||||
extern string overlay;
|
||||
extern string clock;
|
||||
extern uid_t real_uid, set_uid;
|
||||
}
|
||||
|
||||
namespace Runner {
|
||||
|
|
|
@ -406,6 +406,18 @@ namespace Logger {
|
|||
size_t loglevel;
|
||||
fs::path logfile;
|
||||
|
||||
//* Wrapper for lowering priviliges if using SUID bit and currently isn't using real userid
|
||||
class lose_priv {
|
||||
int status = -1;
|
||||
public:
|
||||
lose_priv() {
|
||||
if (geteuid() != Global::real_uid) this->status = seteuid(Global::real_uid);
|
||||
}
|
||||
~lose_priv() {
|
||||
if (status == 0) status = seteuid(Global::set_uid);
|
||||
}
|
||||
};
|
||||
|
||||
void set(const string& level) {
|
||||
loglevel = v_index(log_levels, level);
|
||||
}
|
||||
|
@ -413,6 +425,7 @@ namespace Logger {
|
|||
void log_write(const size_t level, const string& msg) {
|
||||
if (loglevel < level or logfile.empty()) return;
|
||||
atomic_lock lck(busy, true);
|
||||
lose_priv neutered{};
|
||||
std::error_code ec;
|
||||
try {
|
||||
if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) {
|
||||
|
|
Loading…
Reference in a new issue