basic user, group and capability housekeeping.
[lunaix-os.git] / lunaix-os / kernel / usrscope.c
1 #include <lunaix/usrscope.h>
2 #include <lunaix/mm/valloc.h>
3 #include <lunaix/status.h>
4 #include <lunaix/spike.h>
5 #include <lunaix/process.h>
6
7 #include <klibc/string.h>
8
9 #define GLIST_INIT_LEN      8
10
11 static struct ugroup_obj*
12 __alloc_groups_obj(unsigned int len)
13 {
14     unsigned int size;
15     struct ugroup_obj* ugo;
16
17     assert(len >= GLIST_INIT_LEN);
18     
19     ugo = valloc(sizeof(*ugo));
20     ugo->refs = 1;
21
22     size = len * sizeof(gid_t);
23     ugo->list = valloc(size);
24     ugo->maxcap = size;
25
26     memset(ugo->list, grp_list_end, size);
27     return ugo;
28 }
29
30 static inline void
31 __ref_groups_obj(struct ugroup_obj* ugo)
32 {
33     ugo->refs++;
34 }
35
36 static void
37 __unref_groups_obj(struct ugroup_obj* ugo)
38 {
39     ugo->refs--;
40     if (ugo->refs) {
41         return;
42     }
43
44     vfree_safe(ugo->list);
45     vfree(ugo);
46 }
47
48 static struct ugroup_obj*
49 __modify_group_obj(struct user_scope* procu, unsigned int new_len)
50 {
51     struct ugroup_obj* ugo;
52
53     ugo = procu->grps;
54     if (!ugo) {
55         return __alloc_groups_obj(GLIST_INIT_LEN);
56     }
57
58     __unref_groups_obj(ugo);
59
60     new_len = MAX(new_len, ugo->maxcap);
61     ugo = __alloc_groups_obj(new_len);
62     procu->grps = ugo;
63
64     return ugo;
65 }
66
67 int 
68 uscope_setgroups(struct user_scope* proc_usr, 
69                  const gid_t* grps, unsigned int len)
70 {
71     struct ugroup_obj* ugo;
72
73     if (len > NGROUPS_MAX) {
74         return E2BIG;
75     }
76
77     ugo = __modify_group_obj(proc_usr, len);
78     memcpy(ugo->list, grps, len * sizeof(gid_t));
79
80     return 0;
81 }
82
83 bool
84 uscope_membership(struct user_scope* proc_usr, gid_t gid)
85 {
86     struct ugroup_obj* ugo;
87     
88     ugo = proc_usr->grps;
89     if (unlikely(!ugo)) {
90         return false;
91     }
92
93     for (unsigned i = 0; i < ugo->maxcap; i++)
94     {
95         if (ugo->list[i] != grp_list_end) {
96             break;
97         }
98         
99         if (ugo->list[i] == gid) {
100             return true;
101         }
102     }
103     
104     return false;
105 }
106
107 void 
108 uscope_copy(struct user_scope* to, struct user_scope* from)
109 {
110     __ref_groups_obj(from->grps);
111     memcpy(to, from, sizeof(*to));
112 }
113
114
115 enum acl_match
116 check_current_acl(uid_t desired_u, gid_t desired_g)
117 {
118     struct user_scope* uscope;
119
120     if (!__current->euid || __current->euid == desired_u) 
121     {
122         return ACL_MATCH_U;
123     }
124
125     if (__current->egid == desired_g) {
126         return ACL_MATCH_G;
127     }
128
129     uscope = current_user_scope();
130     if (uscope_membership(uscope, desired_g)) {
131         return ACL_MATCH_G;
132     }
133
134     return ACL_NO_MATCH;
135 }