kernel: Simplified manual SU command processing for code
This commit is contained in:
@@ -559,9 +559,7 @@ static void sulog_prctl_cmd(uid_t uid, unsigned long cmd)
|
|||||||
case CMD_GET_APP_PROFILE: name = "prctl_get_app_profile"; break;
|
case CMD_GET_APP_PROFILE: name = "prctl_get_app_profile"; break;
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
#ifdef CONFIG_KSU_MANUAL_SU
|
||||||
case CMD_SU_ESCALATION_REQUEST: name = "prctl_su_escalation_request"; break;
|
case CMD_MANUAL_SU_REQUEST: name = "prctl_manual_su_request"; break;
|
||||||
case CMD_ADD_PENDING_ROOT: name = "prctl_add_pending_root"; break;
|
|
||||||
case CMD_GENERATE_AUTH_TOKEN: name = "prctl_generate_auth_token"; break;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
@@ -605,7 +603,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
|
|
||||||
bool is_manual_su_cmd = false;
|
bool is_manual_su_cmd = false;
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
#ifdef CONFIG_KSU_MANUAL_SU
|
||||||
is_manual_su_cmd = (arg2 == CMD_SU_ESCALATION_REQUEST || arg2 == CMD_ADD_PENDING_ROOT || arg2 == CMD_GENERATE_AUTH_TOKEN );
|
is_manual_su_cmd = (arg2 == CMD_MANUAL_SU_REQUEST);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS
|
#ifdef CONFIG_KSU_SUSFS
|
||||||
@@ -958,64 +956,30 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
#ifdef CONFIG_KSU_MANUAL_SU
|
||||||
if (arg2 == CMD_SU_ESCALATION_REQUEST) {
|
if (arg2 == CMD_MANUAL_SU_REQUEST) {
|
||||||
uid_t target_uid = (uid_t)arg3;
|
struct manual_su_request request;
|
||||||
pid_t target_pid = (pid_t)arg4;
|
int su_option = (int)arg3;
|
||||||
|
|
||||||
int ret = ksu_manual_su_escalate(target_uid, target_pid);
|
if (copy_from_user(&request, (void __user *)arg4, sizeof(request))) {
|
||||||
|
pr_err("manual_su: failed to copy request from user\n");
|
||||||
if (ret == 0 && copy_to_user(result, &reply_ok, sizeof(reply_ok)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg2 == CMD_GENERATE_AUTH_TOKEN) {
|
|
||||||
char __user *token_buffer = (char __user *)arg3;
|
|
||||||
size_t buffer_size = (size_t)arg4;
|
|
||||||
|
|
||||||
if (current_uid().val > 2000) {
|
|
||||||
pr_warn("CMD_GENERATE_AUTH_TOKEN: denied for app UID %d\n", current_uid().val);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_size < KSU_TOKEN_LENGTH + 1) {
|
|
||||||
pr_err("CMD_GENERATE_AUTH_TOKEN: buffer too small\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *new_token = ksu_generate_auth_token();
|
|
||||||
if (!new_token) {
|
|
||||||
pr_err("CMD_GENERATE_AUTH_TOKEN: failed to generate token\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_to_user(token_buffer, new_token, KSU_TOKEN_LENGTH + 1)) {
|
|
||||||
pr_err("CMD_GENERATE_AUTH_TOKEN: failed to copy token to user\n");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
|
||||||
pr_err("CMD_GENERATE_AUTH_TOKEN: prctl reply error\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("prctl: auth token generated successfully\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg2 == CMD_ADD_PENDING_ROOT) {
|
int ret = ksu_handle_manual_su_request(su_option, &request);
|
||||||
uid_t uid = (uid_t)arg3;
|
|
||||||
|
|
||||||
if (!is_current_verified()) {
|
// Copy back result for token generation
|
||||||
pr_warn("CMD_ADD_PENDING_ROOT: denied, password not verified\n");
|
if (ret == 0 && su_option == MANUAL_SU_OP_GENERATE_TOKEN) {
|
||||||
return -EPERM;
|
if (copy_to_user((void __user *)arg4, &request, sizeof(request))) {
|
||||||
|
pr_err("manual_su: failed to copy request back to user\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
|
pr_err("manual_su: prctl reply error\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_pending_root(uid);
|
|
||||||
current_verified = false;
|
|
||||||
pr_info("prctl: pending root added for UID %d\n", uid);
|
|
||||||
|
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok)))
|
|
||||||
pr_err("prctl: CMD_ADD_PENDING_ROOT reply error\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,9 +25,7 @@
|
|||||||
#define CMD_ENABLE_SU 15
|
#define CMD_ENABLE_SU 15
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_MANUAL_SU
|
#ifdef CONFIG_KSU_MANUAL_SU
|
||||||
#define CMD_SU_ESCALATION_REQUEST 50
|
#define CMD_MANUAL_SU_REQUEST 50
|
||||||
#define CMD_ADD_PENDING_ROOT 51
|
|
||||||
#define CMD_GENERATE_AUTH_TOKEN 52
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CMD_GET_FULL_VERSION 0xC0FFEE1A
|
#define CMD_GET_FULL_VERSION 0xC0FFEE1A
|
||||||
|
|||||||
@@ -15,15 +15,10 @@
|
|||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
|
|
||||||
extern void escape_to_root_for_cmd_su(uid_t, pid_t);
|
extern void escape_to_root_for_cmd_su(uid_t, pid_t);
|
||||||
#define MAX_PENDING 16
|
static bool current_verified = false;
|
||||||
#define REMOVE_DELAY_CALLS 150
|
static void ksu_cleanup_expired_tokens(void);
|
||||||
#define MAX_TOKENS 10
|
static bool is_current_verified(void);
|
||||||
|
static void add_pending_root(uid_t uid);
|
||||||
struct pending_uid {
|
|
||||||
uid_t uid;
|
|
||||||
int use_count;
|
|
||||||
int remove_calls;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pending_uid pending_uids[MAX_PENDING] = {0};
|
static struct pending_uid pending_uids[MAX_PENDING] = {0};
|
||||||
static int pending_cnt = 0;
|
static int pending_cnt = 0;
|
||||||
@@ -31,8 +26,6 @@ static struct ksu_token_entry auth_tokens[MAX_TOKENS] = {0};
|
|||||||
static int token_count = 0;
|
static int token_count = 0;
|
||||||
static DEFINE_SPINLOCK(token_lock);
|
static DEFINE_SPINLOCK(token_lock);
|
||||||
|
|
||||||
bool current_verified = false;
|
|
||||||
|
|
||||||
static char* get_token_from_envp(void)
|
static char* get_token_from_envp(void)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
@@ -97,7 +90,7 @@ static char* get_token_from_envp(void)
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ksu_generate_auth_token(void)
|
static char* ksu_generate_auth_token(void)
|
||||||
{
|
{
|
||||||
static char token_buffer[KSU_TOKEN_LENGTH + 1];
|
static char token_buffer[KSU_TOKEN_LENGTH + 1];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@@ -139,7 +132,7 @@ char* ksu_generate_auth_token(void)
|
|||||||
return token_buffer;
|
return token_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ksu_verify_auth_token(const char *token)
|
static bool ksu_verify_auth_token(const char *token)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
@@ -172,7 +165,7 @@ bool ksu_verify_auth_token(const char *token)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_cleanup_expired_tokens(void)
|
static void ksu_cleanup_expired_tokens(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -194,8 +187,29 @@ void ksu_cleanup_expired_tokens(void)
|
|||||||
spin_unlock_irqrestore(&token_lock, flags);
|
spin_unlock_irqrestore(&token_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksu_manual_su_escalate(uid_t target_uid, pid_t target_pid)
|
static int handle_token_generation(struct manual_su_request *request)
|
||||||
{
|
{
|
||||||
|
if (current_uid().val > 2000) {
|
||||||
|
pr_warn("manual_su: token generation denied for app UID %d\n", current_uid().val);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *new_token = ksu_generate_auth_token();
|
||||||
|
if (!new_token) {
|
||||||
|
pr_err("manual_su: failed to generate token\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(request->token_buffer, new_token, KSU_TOKEN_LENGTH + 1);
|
||||||
|
pr_info("manual_su: auth token generated successfully\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_escalation_request(struct manual_su_request *request)
|
||||||
|
{
|
||||||
|
uid_t target_uid = request->target_uid;
|
||||||
|
pid_t target_pid = request->target_pid;
|
||||||
|
|
||||||
if (current_uid().val == 0 || is_manager() || ksu_is_allow_uid(current_uid().val))
|
if (current_uid().val == 0 || is_manager() || ksu_is_allow_uid(current_uid().val))
|
||||||
goto allowed;
|
goto allowed;
|
||||||
|
|
||||||
@@ -219,7 +233,49 @@ allowed:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_current_verified(void)
|
static int handle_add_pending_request(struct manual_su_request *request)
|
||||||
|
{
|
||||||
|
uid_t target_uid = request->target_uid;
|
||||||
|
|
||||||
|
if (!is_current_verified()) {
|
||||||
|
pr_warn("manual_su: add_pending denied, not verified\n");
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_pending_root(target_uid);
|
||||||
|
current_verified = false;
|
||||||
|
pr_info("manual_su: pending root added for UID %d\n", target_uid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ksu_handle_manual_su_request(int option, struct manual_su_request *request)
|
||||||
|
{
|
||||||
|
if (!request) {
|
||||||
|
pr_err("manual_su: invalid request pointer\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option) {
|
||||||
|
case MANUAL_SU_OP_GENERATE_TOKEN:
|
||||||
|
pr_info("manual_su: handling token generation request\n");
|
||||||
|
return handle_token_generation(request);
|
||||||
|
|
||||||
|
case MANUAL_SU_OP_ESCALATE:
|
||||||
|
pr_info("manual_su: handling escalation request for UID %d, PID %d\n",
|
||||||
|
request->target_uid, request->target_pid);
|
||||||
|
return handle_escalation_request(request);
|
||||||
|
|
||||||
|
case MANUAL_SU_OP_ADD_PENDING:
|
||||||
|
pr_info("manual_su: handling add pending request for UID %d\n", request->target_uid);
|
||||||
|
return handle_add_pending_request(request);
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_err("manual_su: unknown option %d\n", option);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_current_verified(void)
|
||||||
{
|
{
|
||||||
return current_verified;
|
return current_verified;
|
||||||
}
|
}
|
||||||
@@ -255,7 +311,7 @@ void remove_pending_root(uid_t uid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_pending_root(uid_t uid)
|
static void add_pending_root(uid_t uid)
|
||||||
{
|
{
|
||||||
if (pending_cnt >= MAX_PENDING) {
|
if (pending_cnt >= MAX_PENDING) {
|
||||||
pr_warn("pending_root: cache full\n");
|
pr_warn("pending_root: cache full\n");
|
||||||
|
|||||||
@@ -9,10 +9,30 @@
|
|||||||
#define mmap_lock mmap_sem
|
#define mmap_lock mmap_sem
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_PENDING 16
|
||||||
|
#define REMOVE_DELAY_CALLS 150
|
||||||
|
#define MAX_TOKENS 10
|
||||||
|
|
||||||
#define KSU_SU_VERIFIED_BIT (1UL << 0)
|
#define KSU_SU_VERIFIED_BIT (1UL << 0)
|
||||||
#define KSU_TOKEN_LENGTH 32
|
#define KSU_TOKEN_LENGTH 32
|
||||||
#define KSU_TOKEN_ENV_NAME "KSU_AUTH_TOKEN"
|
#define KSU_TOKEN_ENV_NAME "KSU_AUTH_TOKEN"
|
||||||
#define KSU_TOKEN_EXPIRE_TIME 60
|
#define KSU_TOKEN_EXPIRE_TIME 150
|
||||||
|
|
||||||
|
#define MANUAL_SU_OP_GENERATE_TOKEN 0
|
||||||
|
#define MANUAL_SU_OP_ESCALATE 1
|
||||||
|
#define MANUAL_SU_OP_ADD_PENDING 2
|
||||||
|
|
||||||
|
struct pending_uid {
|
||||||
|
uid_t uid;
|
||||||
|
int use_count;
|
||||||
|
int remove_calls;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct manual_su_request {
|
||||||
|
uid_t target_uid;
|
||||||
|
pid_t target_pid;
|
||||||
|
char token_buffer[KSU_TOKEN_LENGTH + 1];
|
||||||
|
};
|
||||||
|
|
||||||
struct ksu_token_entry {
|
struct ksu_token_entry {
|
||||||
char token[KSU_TOKEN_LENGTH + 1];
|
char token[KSU_TOKEN_LENGTH + 1];
|
||||||
@@ -20,13 +40,7 @@ struct ksu_token_entry {
|
|||||||
bool used;
|
bool used;
|
||||||
};
|
};
|
||||||
|
|
||||||
int ksu_manual_su_escalate(uid_t target_uid, pid_t target_pid);
|
int ksu_handle_manual_su_request(int option, struct manual_su_request *request);
|
||||||
bool is_pending_root(uid_t uid);
|
bool is_pending_root(uid_t uid);
|
||||||
void remove_pending_root(uid_t uid);
|
void remove_pending_root(uid_t uid);
|
||||||
void add_pending_root(uid_t uid);
|
|
||||||
bool is_current_verified(void);
|
|
||||||
char* ksu_generate_auth_token(void);
|
|
||||||
bool ksu_verify_auth_token(const char *token);
|
|
||||||
void ksu_cleanup_expired_tokens(void);
|
|
||||||
extern bool current_verified;
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user