diff --git a/drivers/accesstokenid/access_tokenid.c b/drivers/accesstokenid/access_tokenid.c index fd2e73033c3748057d1b7c6370f331c5ba529c6e..32610d1e12204deefaa34aea2c92e1e22f1dcc20 100644 --- a/drivers/accesstokenid/access_tokenid.c +++ b/drivers/accesstokenid/access_tokenid.c @@ -12,9 +12,16 @@ #include #include #include +#include #include #include "access_tokenid.h" +DEFINE_RWLOCK(token_rwlock); +#define ACCESS_TOKEN_UID KUIDT_INIT(3081) + +static struct token_perm_node *g_token_perm_head = NULL; +static struct token_perm_node *g_token_perm_tail = NULL; + int access_tokenid_get_tokenid(struct file *file, void __user *uarg) { return copy_to_user(uarg, ¤t->token, @@ -108,6 +115,132 @@ int access_tokenid_set_ftokenid(struct file *file, void __user *uarg) return 0; } +static bool check_permission_for_set_token_permission() +{ + kuid_t uid = current_uid(); + printk(KERN_INFO "AccessToken: check permission, uid: %d.\n", uid); + return uid_eq(uid, ACCESS_TOKEN_UID); +} + +int access_tokenid_add_permission(struct file *file, void __user *uarg) +{ + printk(KERN_INFO "AccessToken: access_tokenid_add_permission start.\n"); + if (!check_permission_for_set_token_permission()) + return -EPERM; + + ioctl_add_perm_data perm_data; + if (copy_from_user(&perm_data, uarg, sizeof(perm_data))) { + return -EFAULT; + } + struct token_perm_node *node = kzalloc(sizeof(*node), GFP_ATOMIC); + if (node == NULL) { + return -ENOMEM; + } + memcpy(&node->perm_data, &perm_data, sizeof(perm_data)); + write_lock_irq(&token_rwlock); + if (g_token_perm_head == NULL) { + g_token_perm_head = node; + } else { + g_token_perm_tail->next = node; + } + + g_token_perm_tail = node; + write_unlock_irq(&token_rwlock); + return 0; +} + +int access_tokenid_remove_permission(struct file *file, void __user *uarg) +{ + printk(KERN_INFO "AccessToken: access_tokenid_remove_permission start.\n"); + if (!check_permission_for_set_token_permission()) + return -EPERM; + + int32_t token = 0; + if (copy_from_user(&token, uarg, sizeof(token))) + return -EFAULT; + + printk(KERN_INFO "AccessToken: remove, token: %d.\n", token); + write_lock_irq(&token_rwlock); + struct token_perm_node *current_node = g_token_perm_head; + struct token_perm_node *pre_node = NULL; + while (current_node != NULL) { + if (current_node->perm_data.token != token) { + pre_node = current_node; + current_node = current_node->next; + continue; + } + if (current_node == g_token_perm_head) { + g_token_perm_head = current_node->next; + } else { + pre_node->next = current_node->next; + } + if (current_node == g_token_perm_tail) { + g_token_perm_tail = pre_node; + } + kfree(current_node); + current_node = NULL; + } + write_unlock_irq(&token_rwlock); + return 0; +} + +int access_tokenid_set_permission(struct file *file, void __user *uarg) +{ + printk(KERN_INFO "AccessToken: access_tokenid_set_permission start.\n"); + if (!check_permission_for_set_token_permission()) + return -EPERM; + + ioctl_set_get_perm_data set_perm_data; + if (copy_from_user(&set_perm_data, uarg, sizeof(set_perm_data))) + return -EFAULT; + + printk(KERN_INFO "AccessToken: set, token: %d.\n", set_perm_data.token); + write_lock_irq(&token_rwlock); + struct token_perm_node *current_node = g_token_perm_head; + while (current_node != NULL) { + if (current_node->perm_data.token == set_perm_data.token) { + uint32_t idx = set_perm_data.opCode / MAX_PERM_SIZE; + uint32_t bitIdx = set_perm_data.opCode % MAX_PERM_SIZE; + if (set_perm_data.isGranted) { + current_node->perm_data.perm[idx] |= (uint64_t)0x01 << bitIdx; + } else { + current_node->perm_data.perm[idx] &= ~((uint64_t)0x01 << bitIdx); + } + break; + } + current_node = current_node->next; + } + write_unlock_irq(&token_rwlock); + printk(KERN_INFO "AccessToken: set successfully.\n"); + return 0; +} + +int access_tokenid_get_permission(struct file *file, void __user *uarg) +{ + printk(KERN_INFO "AccessToken: access_tokenid_get_permission start.\n"); + ioctl_set_get_perm_data get_perm_data; + if (copy_from_user(&get_perm_data, uarg, sizeof(get_perm_data))) + return -EFAULT; + get_perm_data.isGranted = false; + printk(KERN_INFO "AccessToken: get, token: %d.\n", get_perm_data.token); + read_lock(&token_rwlock); + struct token_perm_node *current_node = g_token_perm_head; + while (current_node != NULL) { + if (current_node->perm_data.token == get_perm_data.token) { + uint32_t idx = get_perm_data.opCode / MAX_PERM_SIZE; + uint32_t bitIdx = get_perm_data.opCode % MAX_PERM_SIZE; + printk(KERN_INFO "AccessToken: get find token: %d\n", get_perm_data.token); + printk(KERN_INFO "AccessToken: get find perm: %llu\n", current_node->perm_data.perm[idx]); + get_perm_data.isGranted = (current_node->perm_data.perm[idx] & (uint64_t)0x01 << bitIdx) != 0; + break; + } + current_node = current_node->next; + } + read_unlock(&token_rwlock); + printk(KERN_INFO "AccessToken: get isGranted: %d.\n", get_perm_data.isGranted); + return copy_to_user(uarg, &get_perm_data, sizeof(get_perm_data)) ? -EFAULT : 0; +} + typedef int (*access_token_id_func)(struct file *file, void __user *arg); static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = { @@ -116,6 +249,10 @@ static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = { access_tokenid_set_tokenid, access_tokenid_get_ftokenid, access_tokenid_set_ftokenid, + access_tokenid_add_permission, + access_tokenid_remove_permission, + access_tokenid_get_permission, + access_tokenid_set_permission, }; static long access_tokenid_ioctl(struct file *file, unsigned int cmd, diff --git a/drivers/accesstokenid/access_tokenid.h b/drivers/accesstokenid/access_tokenid.h index 8a25d5f0fa5caf71a1a3af8f9d0d4bf0628b1c61..0f0c57966afbbc8deed812e093cc3be85a05e304 100644 --- a/drivers/accesstokenid/access_tokenid.h +++ b/drivers/accesstokenid/access_tokenid.h @@ -10,15 +10,21 @@ #define _ACCESS_TOKEN_ID_H #include +#include #include #define ACCESS_TOKEN_ID_IOCTL_BASE 'A' +#define MAX_PERM_SIZE 64 enum { GET_TOKEN_ID = 1, SET_TOKEN_ID, GET_FTOKEN_ID, SET_FTOKEN_ID, + ADD_PERMISSIONS, + REMOVE_PERMISSIONS, + GET_PERMISSION, + SET_PERMISSION, ACCESS_TOKENID_MAX_NR }; @@ -31,6 +37,22 @@ typedef struct { unsigned int version : 3; } access_tokenid_inner; +typedef struct { + uint32_t token; + uint32_t opCode; + bool isGranted; +} ioctl_set_get_perm_data; + +typedef struct { + uint32_t token; + uint64_t perm[MAX_PERM_SIZE]; +} ioctl_add_perm_data; + +typedef struct token_perm_node { + ioctl_add_perm_data perm_data; + struct token_perm_node *next; +}; + #define ACCESS_TOKENID_GET_TOKENID \ _IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_TOKEN_ID, unsigned long long) #define ACCESS_TOKENID_SET_TOKENID \ @@ -39,5 +61,13 @@ typedef struct { _IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_FTOKEN_ID, unsigned long long) #define ACCESS_TOKENID_SET_FTOKENID \ _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_FTOKEN_ID, unsigned long long) +#define ACCESS_TOKENID_ADD_PERMISSIONS \ + _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, ADD_PERMISSIONS, ioctl_add_perm_data) +#define ACCESS_TOKENID_REMOVE_PERMISSIONS \ + _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, REMOVE_PERMISSIONS, uint32_t) +#define ACCESS_TOKENID_GET_PERMISSION \ + _IOWR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_PERMISSION, ioctl_set_get_perm_data) +#define ACCESS_TOKENID_SET_PERMISSION \ + _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_PERMISSION, ioctl_set_get_perm_data) #endif /* _ACCESS_TOKEN_ID_H */