~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/ipe/policy_parser.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /security/ipe/policy_parser.c (Version linux-6.12-rc7) and /security/ipe/policy_parser.c (Version linux-4.4.302)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * Copyright (C) 2020-2024 Microsoft Corporati    
  4  */                                               
  5                                                   
  6 #include <linux/err.h>                            
  7 #include <linux/slab.h>                           
  8 #include <linux/parser.h>                         
  9 #include <linux/types.h>                          
 10 #include <linux/ctype.h>                          
 11                                                   
 12 #include "policy.h"                               
 13 #include "policy_parser.h"                        
 14 #include "digest.h"                               
 15                                                   
 16 #define START_COMMENT   '#'                       
 17 #define IPE_POLICY_DELIM " \t"                    
 18 #define IPE_LINE_DELIM "\n\r"                     
 19                                                   
 20 /**                                               
 21  * new_parsed_policy() - Allocate and initiali    
 22  *                                                
 23  * Return:                                        
 24  * * a pointer to the ipe_parsed_policy struct    
 25  * * %-ENOMEM                                     
 26  */                                               
 27 static struct ipe_parsed_policy *new_parsed_po    
 28 {                                                 
 29         struct ipe_parsed_policy *p = NULL;       
 30         struct ipe_op_table *t = NULL;            
 31         size_t i = 0;                             
 32                                                   
 33         p = kzalloc(sizeof(*p), GFP_KERNEL);      
 34         if (!p)                                   
 35                 return ERR_PTR(-ENOMEM);          
 36                                                   
 37         p->global_default_action = IPE_ACTION_    
 38                                                   
 39         for (i = 0; i < ARRAY_SIZE(p->rules);     
 40                 t = &p->rules[i];                 
 41                                                   
 42                 t->default_action = IPE_ACTION    
 43                 INIT_LIST_HEAD(&t->rules);        
 44         }                                         
 45                                                   
 46         return p;                                 
 47 }                                                 
 48                                                   
 49 /**                                               
 50  * remove_comment() - Truncate all chars follo    
 51  *                                                
 52  * @line: Supplies a policy line string for pr    
 53  */                                               
 54 static void remove_comment(char *line)            
 55 {                                                 
 56         line = strchr(line, START_COMMENT);       
 57                                                   
 58         if (line)                                 
 59                 *line = '\0';                     
 60 }                                                 
 61                                                   
 62 /**                                               
 63  * remove_trailing_spaces() - Truncate all tra    
 64  *                                                
 65  * @line: Supplies a policy line string for pr    
 66  *                                                
 67  * Return: The length of truncated string.        
 68  */                                               
 69 static size_t remove_trailing_spaces(char *lin    
 70 {                                                 
 71         size_t i = 0;                             
 72                                                   
 73         i = strlen(line);                         
 74         while (i > 0 && isspace(line[i - 1]))     
 75                 i--;                              
 76                                                   
 77         line[i] = '\0';                           
 78                                                   
 79         return i;                                 
 80 }                                                 
 81                                                   
 82 /**                                               
 83  * parse_version() - Parse policy version.        
 84  * @ver: Supplies a version string to be parse    
 85  * @p: Supplies the partial parsed policy.        
 86  *                                                
 87  * Return:                                        
 88  * * %0         - Success                         
 89  * * %-EBADMSG  - Version string is invalid       
 90  * * %-ERANGE   - Version number overflow         
 91  * * %-EINVAL   - Parsing error                   
 92  */                                               
 93 static int parse_version(char *ver, struct ipe    
 94 {                                                 
 95         u16 *const cv[] = { &p->version.major,    
 96         size_t sep_count = 0;                     
 97         char *token;                              
 98         int rc = 0;                               
 99                                                   
100         while ((token = strsep(&ver, ".")) !=     
101                 /* prevent overflow */            
102                 if (sep_count >= ARRAY_SIZE(cv    
103                         return -EBADMSG;          
104                                                   
105                 rc = kstrtou16(token, 10, cv[s    
106                 if (rc)                           
107                         return rc;                
108                                                   
109                 ++sep_count;                      
110         }                                         
111                                                   
112         /* prevent underflow */                   
113         if (sep_count != ARRAY_SIZE(cv))          
114                 return -EBADMSG;                  
115                                                   
116         return 0;                                 
117 }                                                 
118                                                   
119 enum header_opt {                                 
120         IPE_HEADER_POLICY_NAME = 0,               
121         IPE_HEADER_POLICY_VERSION,                
122         __IPE_HEADER_MAX                          
123 };                                                
124                                                   
125 static const match_table_t header_tokens = {      
126         {IPE_HEADER_POLICY_NAME,        "polic    
127         {IPE_HEADER_POLICY_VERSION,     "polic    
128         {__IPE_HEADER_MAX,              NULL}     
129 };                                                
130                                                   
131 /**                                               
132  * parse_header() - Parse policy header inform    
133  * @line: Supplies header line to be parsed.      
134  * @p: Supplies the partial parsed policy.        
135  *                                                
136  * Return:                                        
137  * * %0         - Success                         
138  * * %-EBADMSG  - Header string is invalid        
139  * * %-ENOMEM   - Out of memory (OOM)             
140  * * %-ERANGE   - Version number overflow         
141  * * %-EINVAL   - Version parsing error           
142  */                                               
143 static int parse_header(char *line, struct ipe    
144 {                                                 
145         substring_t args[MAX_OPT_ARGS];           
146         char *t, *ver = NULL;                     
147         size_t idx = 0;                           
148         int rc = 0;                               
149                                                   
150         while ((t = strsep(&line, IPE_POLICY_D    
151                 int token;                        
152                                                   
153                 if (*t == '\0')                   
154                         continue;                 
155                 if (idx >= __IPE_HEADER_MAX) {    
156                         rc = -EBADMSG;            
157                         goto out;                 
158                 }                                 
159                                                   
160                 token = match_token(t, header_    
161                 if (token != idx) {               
162                         rc = -EBADMSG;            
163                         goto out;                 
164                 }                                 
165                                                   
166                 switch (token) {                  
167                 case IPE_HEADER_POLICY_NAME:      
168                         p->name = match_strdup    
169                         if (!p->name)             
170                                 rc = -ENOMEM;     
171                         break;                    
172                 case IPE_HEADER_POLICY_VERSION    
173                         ver = match_strdup(&ar    
174                         if (!ver) {               
175                                 rc = -ENOMEM;     
176                                 break;            
177                         }                         
178                         rc = parse_version(ver    
179                         break;                    
180                 default:                          
181                         rc = -EBADMSG;            
182                 }                                 
183                 if (rc)                           
184                         goto out;                 
185                 ++idx;                            
186         }                                         
187                                                   
188         if (idx != __IPE_HEADER_MAX)              
189                 rc = -EBADMSG;                    
190                                                   
191 out:                                              
192         kfree(ver);                               
193         return rc;                                
194 }                                                 
195                                                   
196 /**                                               
197  * token_default() - Determine if the given to    
198  * @token: Supplies the token string to be com    
199  *                                                
200  * Return:                                        
201  * * %false     - The token is not "DEFAULT"      
202  * * %true      - The token is "DEFAULT"          
203  */                                               
204 static bool token_default(char *token)            
205 {                                                 
206         return !strcmp(token, "DEFAULT");         
207 }                                                 
208                                                   
209 /**                                               
210  * free_rule() - Free the supplied ipe_rule st    
211  * @r: Supplies the ipe_rule struct to be free    
212  *                                                
213  * Free a ipe_rule struct @r. Note @r must be     
214  * calling this function.                         
215  */                                               
216 static void free_rule(struct ipe_rule *r)         
217 {                                                 
218         struct ipe_prop *p, *t;                   
219                                                   
220         if (IS_ERR_OR_NULL(r))                    
221                 return;                           
222                                                   
223         list_for_each_entry_safe(p, t, &r->pro    
224                 list_del(&p->next);               
225                 ipe_digest_free(p->value);        
226                 kfree(p);                         
227         }                                         
228                                                   
229         kfree(r);                                 
230 }                                                 
231                                                   
232 static const match_table_t operation_tokens =     
233         {IPE_OP_EXEC,                   "op=EX    
234         {IPE_OP_FIRMWARE,               "op=FI    
235         {IPE_OP_KERNEL_MODULE,          "op=KM    
236         {IPE_OP_KEXEC_IMAGE,            "op=KE    
237         {IPE_OP_KEXEC_INITRAMFS,        "op=KE    
238         {IPE_OP_POLICY,                 "op=PO    
239         {IPE_OP_X509,                   "op=X5    
240         {IPE_OP_INVALID,                NULL}     
241 };                                                
242                                                   
243 /**                                               
244  * parse_operation() - Parse the operation typ    
245  * @t: Supplies the token string to be parsed.    
246  *                                                
247  * Return: The parsed operation type.             
248  */                                               
249 static enum ipe_op_type parse_operation(char *    
250 {                                                 
251         substring_t args[MAX_OPT_ARGS];           
252                                                   
253         return match_token(t, operation_tokens    
254 }                                                 
255                                                   
256 static const match_table_t action_tokens = {      
257         {IPE_ACTION_ALLOW,      "action=ALLOW"    
258         {IPE_ACTION_DENY,       "action=DENY"}    
259         {IPE_ACTION_INVALID,    NULL}             
260 };                                                
261                                                   
262 /**                                               
263  * parse_action() - Parse the action type give    
264  * @t: Supplies the token string to be parsed.    
265  *                                                
266  * Return: The parsed action type.                
267  */                                               
268 static enum ipe_action_type parse_action(char     
269 {                                                 
270         substring_t args[MAX_OPT_ARGS];           
271                                                   
272         return match_token(t, action_tokens, a    
273 }                                                 
274                                                   
275 static const match_table_t property_tokens = {    
276         {IPE_PROP_BOOT_VERIFIED_FALSE,  "boot_    
277         {IPE_PROP_BOOT_VERIFIED_TRUE,   "boot_    
278         {IPE_PROP_DMV_ROOTHASH,         "dmver    
279         {IPE_PROP_DMV_SIG_FALSE,        "dmver    
280         {IPE_PROP_DMV_SIG_TRUE,         "dmver    
281         {IPE_PROP_FSV_DIGEST,           "fsver    
282         {IPE_PROP_FSV_SIG_FALSE,        "fsver    
283         {IPE_PROP_FSV_SIG_TRUE,         "fsver    
284         {IPE_PROP_INVALID,              NULL}     
285 };                                                
286                                                   
287 /**                                               
288  * parse_property() - Parse a rule property gi    
289  * @t: Supplies the token string to be parsed.    
290  * @r: Supplies the ipe_rule the parsed proper    
291  *                                                
292  * This function parses and associates a prope    
293  * on a token string.                             
294  *                                                
295  * Return:                                        
296  * * %0         - Success                         
297  * * %-ENOMEM   - Out of memory (OOM)             
298  * * %-EBADMSG  - The supplied token cannot be    
299  */                                               
300 static int parse_property(char *t, struct ipe_    
301 {                                                 
302         substring_t args[MAX_OPT_ARGS];           
303         struct ipe_prop *p = NULL;                
304         int rc = 0;                               
305         int token;                                
306         char *dup = NULL;                         
307                                                   
308         p = kzalloc(sizeof(*p), GFP_KERNEL);      
309         if (!p)                                   
310                 return -ENOMEM;                   
311                                                   
312         token = match_token(t, property_tokens    
313                                                   
314         switch (token) {                          
315         case IPE_PROP_DMV_ROOTHASH:               
316         case IPE_PROP_FSV_DIGEST:                 
317                 dup = match_strdup(&args[0]);     
318                 if (!dup) {                       
319                         rc = -ENOMEM;             
320                         goto err;                 
321                 }                                 
322                 p->value = ipe_digest_parse(du    
323                 if (IS_ERR(p->value)) {           
324                         rc = PTR_ERR(p->value)    
325                         goto err;                 
326                 }                                 
327                 fallthrough;                      
328         case IPE_PROP_BOOT_VERIFIED_FALSE:        
329         case IPE_PROP_BOOT_VERIFIED_TRUE:         
330         case IPE_PROP_DMV_SIG_FALSE:              
331         case IPE_PROP_DMV_SIG_TRUE:               
332         case IPE_PROP_FSV_SIG_FALSE:              
333         case IPE_PROP_FSV_SIG_TRUE:               
334                 p->type = token;                  
335                 break;                            
336         default:                                  
337                 rc = -EBADMSG;                    
338                 break;                            
339         }                                         
340         if (rc)                                   
341                 goto err;                         
342         list_add_tail(&p->next, &r->props);       
343                                                   
344 out:                                              
345         kfree(dup);                               
346         return rc;                                
347 err:                                              
348         kfree(p);                                 
349         goto out;                                 
350 }                                                 
351                                                   
352 /**                                               
353  * parse_rule() - parse a policy rule line.       
354  * @line: Supplies rule line to be parsed.        
355  * @p: Supplies the partial parsed policy.        
356  *                                                
357  * Return:                                        
358  * * 0          - Success                         
359  * * %-ENOMEM   - Out of memory (OOM)             
360  * * %-EBADMSG  - Policy syntax error             
361  */                                               
362 static int parse_rule(char *line, struct ipe_p    
363 {                                                 
364         enum ipe_action_type action = IPE_ACTI    
365         enum ipe_op_type op = IPE_OP_INVALID;     
366         bool is_default_rule = false;             
367         struct ipe_rule *r = NULL;                
368         bool first_token = true;                  
369         bool op_parsed = false;                   
370         int rc = 0;                               
371         char *t;                                  
372                                                   
373         if (IS_ERR_OR_NULL(line))                 
374                 return -EBADMSG;                  
375                                                   
376         r = kzalloc(sizeof(*r), GFP_KERNEL);      
377         if (!r)                                   
378                 return -ENOMEM;                   
379                                                   
380         INIT_LIST_HEAD(&r->next);                 
381         INIT_LIST_HEAD(&r->props);                
382                                                   
383         while (t = strsep(&line, IPE_POLICY_DE    
384                 if (*t == '\0')                   
385                         continue;                 
386                 if (first_token && token_defau    
387                         is_default_rule = true    
388                 } else {                          
389                         if (!op_parsed) {         
390                                 op = parse_ope    
391                                 if (op == IPE_    
392                                         rc = -    
393                                 else              
394                                         op_par    
395                         } else {                  
396                                 rc = parse_pro    
397                         }                         
398                 }                                 
399                                                   
400                 if (rc)                           
401                         goto err;                 
402                 first_token = false;              
403         }                                         
404                                                   
405         action = parse_action(t);                 
406         if (action == IPE_ACTION_INVALID) {       
407                 rc = -EBADMSG;                    
408                 goto err;                         
409         }                                         
410                                                   
411         if (is_default_rule) {                    
412                 if (!list_empty(&r->props)) {     
413                         rc = -EBADMSG;            
414                 } else if (op == IPE_OP_INVALI    
415                         if (p->global_default_    
416                                 rc = -EBADMSG;    
417                         else                      
418                                 p->global_defa    
419                 } else {                          
420                         if (p->rules[op].defau    
421                                 rc = -EBADMSG;    
422                         else                      
423                                 p->rules[op].d    
424                 }                                 
425         } else if (op != IPE_OP_INVALID && act    
426                 r->op = op;                       
427                 r->action = action;               
428         } else {                                  
429                 rc = -EBADMSG;                    
430         }                                         
431                                                   
432         if (rc)                                   
433                 goto err;                         
434         if (!is_default_rule)                     
435                 list_add_tail(&r->next, &p->ru    
436         else                                      
437                 free_rule(r);                     
438                                                   
439         return rc;                                
440 err:                                              
441         free_rule(r);                             
442         return rc;                                
443 }                                                 
444                                                   
445 /**                                               
446  * ipe_free_parsed_policy() - free a parsed po    
447  * @p: Supplies the parsed policy.                
448  */                                               
449 void ipe_free_parsed_policy(struct ipe_parsed_    
450 {                                                 
451         struct ipe_rule *pp, *t;                  
452         size_t i = 0;                             
453                                                   
454         if (IS_ERR_OR_NULL(p))                    
455                 return;                           
456                                                   
457         for (i = 0; i < ARRAY_SIZE(p->rules);     
458                 list_for_each_entry_safe(pp, t    
459                         list_del(&pp->next);      
460                         free_rule(pp);            
461                 }                                 
462                                                   
463         kfree(p->name);                           
464         kfree(p);                                 
465 }                                                 
466                                                   
467 /**                                               
468  * validate_policy() - validate a parsed polic    
469  * @p: Supplies the fully parsed policy.          
470  *                                                
471  * Given a policy structure that was just pars    
472  * operations have their default rules or a gl    
473  *                                                
474  * Return:                                        
475  * * %0         - Success                         
476  * * %-EBADMSG  - Policy is invalid               
477  */                                               
478 static int validate_policy(const struct ipe_pa    
479 {                                                 
480         size_t i = 0;                             
481                                                   
482         if (p->global_default_action != IPE_AC    
483                 return 0;                         
484                                                   
485         for (i = 0; i < ARRAY_SIZE(p->rules);     
486                 if (p->rules[i].default_action    
487                         return -EBADMSG;          
488         }                                         
489                                                   
490         return 0;                                 
491 }                                                 
492                                                   
493 /**                                               
494  * ipe_parse_policy() - Given a string, parse     
495  * @p: partially filled ipe_policy structure t    
496  *     it must have text and textlen set.         
497  *                                                
498  * Return:                                        
499  * * %0         - Success                         
500  * * %-EBADMSG  - Policy is invalid               
501  * * %-ENOMEM   - Out of Memory                   
502  * * %-ERANGE   - Policy version number overfl    
503  * * %-EINVAL   - Policy version parsing error    
504  */                                               
505 int ipe_parse_policy(struct ipe_policy *p)        
506 {                                                 
507         struct ipe_parsed_policy *pp = NULL;      
508         char *policy = NULL, *dup = NULL;         
509         bool header_parsed = false;               
510         char *line = NULL;                        
511         size_t len;                               
512         int rc = 0;                               
513                                                   
514         if (!p->textlen)                          
515                 return -EBADMSG;                  
516                                                   
517         policy = kmemdup_nul(p->text, p->textl    
518         if (!policy)                              
519                 return -ENOMEM;                   
520         dup = policy;                             
521                                                   
522         pp = new_parsed_policy();                 
523         if (IS_ERR(pp)) {                         
524                 rc = PTR_ERR(pp);                 
525                 goto out;                         
526         }                                         
527                                                   
528         while ((line = strsep(&policy, IPE_LIN    
529                 remove_comment(line);             
530                 len = remove_trailing_spaces(l    
531                 if (!len)                         
532                         continue;                 
533                                                   
534                 if (!header_parsed) {             
535                         rc = parse_header(line    
536                         if (rc)                   
537                                 goto err;         
538                         header_parsed = true;     
539                 } else {                          
540                         rc = parse_rule(line,     
541                         if (rc)                   
542                                 goto err;         
543                 }                                 
544         }                                         
545                                                   
546         if (!header_parsed || validate_policy(    
547                 rc = -EBADMSG;                    
548                 goto err;                         
549         }                                         
550                                                   
551         p->parsed = pp;                           
552                                                   
553 out:                                              
554         kfree(dup);                               
555         return rc;                                
556 err:                                              
557         ipe_free_parsed_policy(pp);               
558         goto out;                                 
559 }                                                 
560                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php