@@ -64,6 +64,8 @@ struct ima_rule_entry {
6464 u8 fsuuid [16 ];
6565 kuid_t uid ;
6666 kuid_t fowner ;
67+ bool (* uid_op )(kuid_t , kuid_t ); /* Handlers for operators */
68+ bool (* fowner_op )(kuid_t , kuid_t ); /* uid_eq(), uid_gt(), uid_lt() */
6769 int pcr ;
6870 struct {
6971 void * rule ; /* LSM file metadata specific */
@@ -83,7 +85,7 @@ struct ima_rule_entry {
8385 * normal users can easily run the machine out of memory simply building
8486 * and running executables.
8587 */
86- static struct ima_rule_entry dont_measure_rules [] = {
88+ static struct ima_rule_entry dont_measure_rules [] __ro_after_init = {
8789 {.action = DONT_MEASURE , .fsmagic = PROC_SUPER_MAGIC , .flags = IMA_FSMAGIC },
8890 {.action = DONT_MEASURE , .fsmagic = SYSFS_MAGIC , .flags = IMA_FSMAGIC },
8991 {.action = DONT_MEASURE , .fsmagic = DEBUGFS_MAGIC , .flags = IMA_FSMAGIC },
@@ -97,32 +99,35 @@ static struct ima_rule_entry dont_measure_rules[] = {
9799 {.action = DONT_MEASURE , .fsmagic = NSFS_MAGIC , .flags = IMA_FSMAGIC }
98100};
99101
100- static struct ima_rule_entry original_measurement_rules [] = {
102+ static struct ima_rule_entry original_measurement_rules [] __ro_after_init = {
101103 {.action = MEASURE , .func = MMAP_CHECK , .mask = MAY_EXEC ,
102104 .flags = IMA_FUNC | IMA_MASK },
103105 {.action = MEASURE , .func = BPRM_CHECK , .mask = MAY_EXEC ,
104106 .flags = IMA_FUNC | IMA_MASK },
105107 {.action = MEASURE , .func = FILE_CHECK , .mask = MAY_READ ,
106- .uid = GLOBAL_ROOT_UID , .flags = IMA_FUNC | IMA_MASK | IMA_UID },
108+ .uid = GLOBAL_ROOT_UID , .uid_op = & uid_eq ,
109+ .flags = IMA_FUNC | IMA_MASK | IMA_UID },
107110 {.action = MEASURE , .func = MODULE_CHECK , .flags = IMA_FUNC },
108111 {.action = MEASURE , .func = FIRMWARE_CHECK , .flags = IMA_FUNC },
109112};
110113
111- static struct ima_rule_entry default_measurement_rules [] = {
114+ static struct ima_rule_entry default_measurement_rules [] __ro_after_init = {
112115 {.action = MEASURE , .func = MMAP_CHECK , .mask = MAY_EXEC ,
113116 .flags = IMA_FUNC | IMA_MASK },
114117 {.action = MEASURE , .func = BPRM_CHECK , .mask = MAY_EXEC ,
115118 .flags = IMA_FUNC | IMA_MASK },
116119 {.action = MEASURE , .func = FILE_CHECK , .mask = MAY_READ ,
117- .uid = GLOBAL_ROOT_UID , .flags = IMA_FUNC | IMA_INMASK | IMA_EUID },
120+ .uid = GLOBAL_ROOT_UID , .uid_op = & uid_eq ,
121+ .flags = IMA_FUNC | IMA_INMASK | IMA_EUID },
118122 {.action = MEASURE , .func = FILE_CHECK , .mask = MAY_READ ,
119- .uid = GLOBAL_ROOT_UID , .flags = IMA_FUNC | IMA_INMASK | IMA_UID },
123+ .uid = GLOBAL_ROOT_UID , .uid_op = & uid_eq ,
124+ .flags = IMA_FUNC | IMA_INMASK | IMA_UID },
120125 {.action = MEASURE , .func = MODULE_CHECK , .flags = IMA_FUNC },
121126 {.action = MEASURE , .func = FIRMWARE_CHECK , .flags = IMA_FUNC },
122127 {.action = MEASURE , .func = POLICY_CHECK , .flags = IMA_FUNC },
123128};
124129
125- static struct ima_rule_entry default_appraise_rules [] = {
130+ static struct ima_rule_entry default_appraise_rules [] __ro_after_init = {
126131 {.action = DONT_APPRAISE , .fsmagic = PROC_SUPER_MAGIC , .flags = IMA_FSMAGIC },
127132 {.action = DONT_APPRAISE , .fsmagic = SYSFS_MAGIC , .flags = IMA_FSMAGIC },
128133 {.action = DONT_APPRAISE , .fsmagic = DEBUGFS_MAGIC , .flags = IMA_FSMAGIC },
@@ -139,10 +144,11 @@ static struct ima_rule_entry default_appraise_rules[] = {
139144 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED },
140145#endif
141146#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
142- {.action = APPRAISE , .fowner = GLOBAL_ROOT_UID , .flags = IMA_FOWNER },
147+ {.action = APPRAISE , .fowner = GLOBAL_ROOT_UID , .fowner_op = & uid_eq ,
148+ .flags = IMA_FOWNER },
143149#else
144150 /* force signature */
145- {.action = APPRAISE , .fowner = GLOBAL_ROOT_UID ,
151+ {.action = APPRAISE , .fowner = GLOBAL_ROOT_UID , . fowner_op = & uid_eq ,
146152 .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED },
147153#endif
148154};
@@ -240,19 +246,20 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
240246 if ((rule -> flags & IMA_FSUUID ) &&
241247 memcmp (rule -> fsuuid , inode -> i_sb -> s_uuid , sizeof (rule -> fsuuid )))
242248 return false;
243- if ((rule -> flags & IMA_UID ) && !uid_eq ( rule -> uid , cred -> uid ))
249+ if ((rule -> flags & IMA_UID ) && !rule -> uid_op ( cred -> uid , rule -> uid ))
244250 return false;
245251 if (rule -> flags & IMA_EUID ) {
246252 if (has_capability_noaudit (current , CAP_SETUID )) {
247- if (!uid_eq ( rule -> uid , cred -> euid )
248- && !uid_eq ( rule -> uid , cred -> suid )
249- && !uid_eq ( rule -> uid , cred -> uid ))
253+ if (!rule -> uid_op ( cred -> euid , rule -> uid )
254+ && !rule -> uid_op ( cred -> suid , rule -> uid )
255+ && !rule -> uid_op ( cred -> uid , rule -> uid ))
250256 return false;
251- } else if (!uid_eq ( rule -> uid , cred -> euid ))
257+ } else if (!rule -> uid_op ( cred -> euid , rule -> uid ))
252258 return false;
253259 }
254260
255- if ((rule -> flags & IMA_FOWNER ) && !uid_eq (rule -> fowner , inode -> i_uid ))
261+ if ((rule -> flags & IMA_FOWNER ) &&
262+ !rule -> fowner_op (inode -> i_uid , rule -> fowner ))
256263 return false;
257264 for (i = 0 ; i < MAX_LSM_RULES ; i ++ ) {
258265 int rc = 0 ;
@@ -486,7 +493,9 @@ enum {
486493 Opt_obj_user , Opt_obj_role , Opt_obj_type ,
487494 Opt_subj_user , Opt_subj_role , Opt_subj_type ,
488495 Opt_func , Opt_mask , Opt_fsmagic ,
489- Opt_fsuuid , Opt_uid , Opt_euid , Opt_fowner ,
496+ Opt_fsuuid , Opt_uid_eq , Opt_euid_eq , Opt_fowner_eq ,
497+ Opt_uid_gt , Opt_euid_gt , Opt_fowner_gt ,
498+ Opt_uid_lt , Opt_euid_lt , Opt_fowner_lt ,
490499 Opt_appraise_type , Opt_permit_directio ,
491500 Opt_pcr
492501};
@@ -507,9 +516,15 @@ static match_table_t policy_tokens = {
507516 {Opt_mask , "mask=%s" },
508517 {Opt_fsmagic , "fsmagic=%s" },
509518 {Opt_fsuuid , "fsuuid=%s" },
510- {Opt_uid , "uid=%s" },
511- {Opt_euid , "euid=%s" },
512- {Opt_fowner , "fowner=%s" },
519+ {Opt_uid_eq , "uid=%s" },
520+ {Opt_euid_eq , "euid=%s" },
521+ {Opt_fowner_eq , "fowner=%s" },
522+ {Opt_uid_gt , "uid>%s" },
523+ {Opt_euid_gt , "euid>%s" },
524+ {Opt_fowner_gt , "fowner>%s" },
525+ {Opt_uid_lt , "uid<%s" },
526+ {Opt_euid_lt , "euid<%s" },
527+ {Opt_fowner_lt , "fowner<%s" },
513528 {Opt_appraise_type , "appraise_type=%s" },
514529 {Opt_permit_directio , "permit_directio" },
515530 {Opt_pcr , "pcr=%s" },
@@ -541,24 +556,37 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
541556 return result ;
542557}
543558
544- static void ima_log_string (struct audit_buffer * ab , char * key , char * value )
559+ static void ima_log_string_op (struct audit_buffer * ab , char * key , char * value ,
560+ bool (* rule_operator )(kuid_t , kuid_t ))
545561{
546- audit_log_format (ab , "%s=" , key );
562+ if (rule_operator == & uid_gt )
563+ audit_log_format (ab , "%s>" , key );
564+ else if (rule_operator == & uid_lt )
565+ audit_log_format (ab , "%s<" , key );
566+ else
567+ audit_log_format (ab , "%s=" , key );
547568 audit_log_untrustedstring (ab , value );
548569 audit_log_format (ab , " " );
549570}
571+ static void ima_log_string (struct audit_buffer * ab , char * key , char * value )
572+ {
573+ ima_log_string_op (ab , key , value , NULL );
574+ }
550575
551576static int ima_parse_rule (char * rule , struct ima_rule_entry * entry )
552577{
553578 struct audit_buffer * ab ;
554579 char * from ;
555580 char * p ;
581+ bool uid_token ;
556582 int result = 0 ;
557583
558584 ab = audit_log_start (NULL , GFP_KERNEL , AUDIT_INTEGRITY_RULE );
559585
560586 entry -> uid = INVALID_UID ;
561587 entry -> fowner = INVALID_UID ;
588+ entry -> uid_op = & uid_eq ;
589+ entry -> fowner_op = & uid_eq ;
562590 entry -> action = UNKNOWN ;
563591 while ((p = strsep (& rule , " \t" )) != NULL ) {
564592 substring_t args [MAX_OPT_ARGS ];
@@ -694,11 +722,21 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
694722 if (!result )
695723 entry -> flags |= IMA_FSUUID ;
696724 break ;
697- case Opt_uid :
698- ima_log_string (ab , "uid" , args [0 ].from );
699- case Opt_euid :
700- if (token == Opt_euid )
701- ima_log_string (ab , "euid" , args [0 ].from );
725+ case Opt_uid_gt :
726+ case Opt_euid_gt :
727+ entry -> uid_op = & uid_gt ;
728+ case Opt_uid_lt :
729+ case Opt_euid_lt :
730+ if ((token == Opt_uid_lt ) || (token == Opt_euid_lt ))
731+ entry -> uid_op = & uid_lt ;
732+ case Opt_uid_eq :
733+ case Opt_euid_eq :
734+ uid_token = (token == Opt_uid_eq ) ||
735+ (token == Opt_uid_gt ) ||
736+ (token == Opt_uid_lt );
737+
738+ ima_log_string_op (ab , uid_token ? "uid" : "euid" ,
739+ args [0 ].from , entry -> uid_op );
702740
703741 if (uid_valid (entry -> uid )) {
704742 result = - EINVAL ;
@@ -713,12 +751,18 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
713751 (uid_t )lnum != lnum )
714752 result = - EINVAL ;
715753 else
716- entry -> flags |= ( token == Opt_uid )
754+ entry -> flags |= uid_token
717755 ? IMA_UID : IMA_EUID ;
718756 }
719757 break ;
720- case Opt_fowner :
721- ima_log_string (ab , "fowner" , args [0 ].from );
758+ case Opt_fowner_gt :
759+ entry -> fowner_op = & uid_gt ;
760+ case Opt_fowner_lt :
761+ if (token == Opt_fowner_lt )
762+ entry -> fowner_op = & uid_lt ;
763+ case Opt_fowner_eq :
764+ ima_log_string_op (ab , "fowner" , args [0 ].from ,
765+ entry -> fowner_op );
722766
723767 if (uid_valid (entry -> fowner )) {
724768 result = - EINVAL ;
@@ -1049,19 +1093,34 @@ int ima_policy_show(struct seq_file *m, void *v)
10491093
10501094 if (entry -> flags & IMA_UID ) {
10511095 snprintf (tbuf , sizeof (tbuf ), "%d" , __kuid_val (entry -> uid ));
1052- seq_printf (m , pt (Opt_uid ), tbuf );
1096+ if (entry -> uid_op == & uid_gt )
1097+ seq_printf (m , pt (Opt_uid_gt ), tbuf );
1098+ else if (entry -> uid_op == & uid_lt )
1099+ seq_printf (m , pt (Opt_uid_lt ), tbuf );
1100+ else
1101+ seq_printf (m , pt (Opt_uid_eq ), tbuf );
10531102 seq_puts (m , " " );
10541103 }
10551104
10561105 if (entry -> flags & IMA_EUID ) {
10571106 snprintf (tbuf , sizeof (tbuf ), "%d" , __kuid_val (entry -> uid ));
1058- seq_printf (m , pt (Opt_euid ), tbuf );
1107+ if (entry -> uid_op == & uid_gt )
1108+ seq_printf (m , pt (Opt_euid_gt ), tbuf );
1109+ else if (entry -> uid_op == & uid_lt )
1110+ seq_printf (m , pt (Opt_euid_lt ), tbuf );
1111+ else
1112+ seq_printf (m , pt (Opt_euid_eq ), tbuf );
10591113 seq_puts (m , " " );
10601114 }
10611115
10621116 if (entry -> flags & IMA_FOWNER ) {
10631117 snprintf (tbuf , sizeof (tbuf ), "%d" , __kuid_val (entry -> fowner ));
1064- seq_printf (m , pt (Opt_fowner ), tbuf );
1118+ if (entry -> fowner_op == & uid_gt )
1119+ seq_printf (m , pt (Opt_fowner_gt ), tbuf );
1120+ else if (entry -> fowner_op == & uid_lt )
1121+ seq_printf (m , pt (Opt_fowner_lt ), tbuf );
1122+ else
1123+ seq_printf (m , pt (Opt_fowner_eq ), tbuf );
10651124 seq_puts (m , " " );
10661125 }
10671126
0 commit comments