1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * A security context is a set of security attributes 4 * associated with each subject and object controlled 5 * by the security policy. Security contexts are 6 * externally represented as variable-length strings 7 * that can be interpreted by a user or application 8 * with an understanding of the security policy. 9 * Internally, the security server uses a simple 10 * structure. This structure is private to the 11 * security server and can be changed without affecting 12 * clients of the security server. 13 * 14 * Author : Stephen Smalley, <stephen.smalley.work@gmail.com> 15 */ 16 17 #ifndef _SS_CONTEXT_H_ 18 #define _SS_CONTEXT_H_ 19 20 #include "ebitmap.h" 21 #include "mls_types.h" 22 #include "security.h" 23 24 /* 25 * A security context consists of an authenticated user 26 * identity, a role, a type and a MLS range. 27 */ 28 struct context { 29 u32 user; 30 u32 role; 31 u32 type; 32 u32 len; /* length of string in bytes */ 33 struct mls_range range; 34 char *str; /* string representation if context cannot be mapped. */ 35 }; 36 37 static inline void mls_context_init(struct context *c) 38 { 39 memset(&c->range, 0, sizeof(c->range)); 40 } 41 42 static inline int mls_context_cpy(struct context *dst, 43 const struct context *src) 44 { 45 int rc; 46 47 dst->range.level[0].sens = src->range.level[0].sens; 48 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); 49 if (rc) 50 goto out; 51 52 dst->range.level[1].sens = src->range.level[1].sens; 53 rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); 54 if (rc) 55 ebitmap_destroy(&dst->range.level[0].cat); 56 out: 57 return rc; 58 } 59 60 /* 61 * Sets both levels in the MLS range of 'dst' to the low level of 'src'. 62 */ 63 static inline int mls_context_cpy_low(struct context *dst, 64 const struct context *src) 65 { 66 int rc; 67 68 dst->range.level[0].sens = src->range.level[0].sens; 69 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); 70 if (rc) 71 goto out; 72 73 dst->range.level[1].sens = src->range.level[0].sens; 74 rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat); 75 if (rc) 76 ebitmap_destroy(&dst->range.level[0].cat); 77 out: 78 return rc; 79 } 80 81 /* 82 * Sets both levels in the MLS range of 'dst' to the high level of 'src'. 83 */ 84 static inline int mls_context_cpy_high(struct context *dst, 85 const struct context *src) 86 { 87 int rc; 88 89 dst->range.level[0].sens = src->range.level[1].sens; 90 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); 91 if (rc) 92 goto out; 93 94 dst->range.level[1].sens = src->range.level[1].sens; 95 rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); 96 if (rc) 97 ebitmap_destroy(&dst->range.level[0].cat); 98 out: 99 return rc; 100 } 101 102 static inline int mls_context_glblub(struct context *dst, 103 const struct context *c1, 104 const struct context *c2) 105 { 106 struct mls_range *dr = &dst->range; 107 const struct mls_range *r1 = &c1->range, *r2 = &c2->range; 108 int rc = 0; 109 110 if (r1->level[1].sens < r2->level[0].sens || 111 r2->level[1].sens < r1->level[0].sens) 112 /* These ranges have no common sensitivities */ 113 return -EINVAL; 114 115 /* Take the greatest of the low */ 116 dr->level[0].sens = max(r1->level[0].sens, r2->level[0].sens); 117 118 /* Take the least of the high */ 119 dr->level[1].sens = min(r1->level[1].sens, r2->level[1].sens); 120 121 rc = ebitmap_and(&dr->level[0].cat, &r1->level[0].cat, 122 &r2->level[0].cat); 123 if (rc) 124 goto out; 125 126 rc = ebitmap_and(&dr->level[1].cat, &r1->level[1].cat, 127 &r2->level[1].cat); 128 if (rc) 129 goto out; 130 131 out: 132 return rc; 133 } 134 135 static inline int mls_context_cmp(const struct context *c1, 136 const struct context *c2) 137 { 138 return ((c1->range.level[0].sens == c2->range.level[0].sens) && 139 ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && 140 (c1->range.level[1].sens == c2->range.level[1].sens) && 141 ebitmap_cmp(&c1->range.level[1].cat, &c2->range.level[1].cat)); 142 } 143 144 static inline void mls_context_destroy(struct context *c) 145 { 146 ebitmap_destroy(&c->range.level[0].cat); 147 ebitmap_destroy(&c->range.level[1].cat); 148 mls_context_init(c); 149 } 150 151 static inline void context_init(struct context *c) 152 { 153 memset(c, 0, sizeof(*c)); 154 } 155 156 static inline int context_cpy(struct context *dst, const struct context *src) 157 { 158 int rc; 159 160 dst->user = src->user; 161 dst->role = src->role; 162 dst->type = src->type; 163 if (src->str) { 164 dst->str = kstrdup(src->str, GFP_ATOMIC); 165 if (!dst->str) 166 return -ENOMEM; 167 dst->len = src->len; 168 } else { 169 dst->str = NULL; 170 dst->len = 0; 171 } 172 rc = mls_context_cpy(dst, src); 173 if (rc) { 174 kfree(dst->str); 175 dst->str = NULL; 176 dst->len = 0; 177 return rc; 178 } 179 return 0; 180 } 181 182 static inline void context_destroy(struct context *c) 183 { 184 c->user = c->role = c->type = 0; 185 kfree(c->str); 186 c->str = NULL; 187 c->len = 0; 188 mls_context_destroy(c); 189 } 190 191 static inline int context_cmp(const struct context *c1, 192 const struct context *c2) 193 { 194 if (c1->len && c2->len) 195 return (c1->len == c2->len && !strcmp(c1->str, c2->str)); 196 if (c1->len || c2->len) 197 return 0; 198 return ((c1->user == c2->user) && (c1->role == c2->role) && 199 (c1->type == c2->type) && mls_context_cmp(c1, c2)); 200 } 201 202 u32 context_compute_hash(const struct context *c); 203 204 #endif /* _SS_CONTEXT_H_ */ 205