Commit 2b4a2474 authored by Tushar Sugandhi's avatar Tushar Sugandhi Committed by Mimi Zohar

IMA: generalize keyring specific measurement constructs

IMA functions such as ima_match_keyring(), process_buffer_measurement(),
ima_match_policy() etc.  handle data specific to keyrings.  Currently,
these constructs are not generic to handle any func specific data.
This makes it harder to extend them without code duplication.

Refactor the keyring specific measurement constructs to be generic and
reusable in other measurement scenarios.
Signed-off-by: default avatarTushar Sugandhi <tusharsu@linux.microsoft.com>
Reviewed-by: default avatarTyler Hicks <tyhicks@linux.microsoft.com>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent ccf11dba
...@@ -256,7 +256,7 @@ static inline void ima_process_queued_keys(void) {} ...@@ -256,7 +256,7 @@ static inline void ima_process_queued_keys(void) {}
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
int mask, enum ima_hooks func, int *pcr, int mask, enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc, struct ima_template_desc **template_desc,
const char *keyring); const char *func_data);
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
int ima_collect_measurement(struct integrity_iint_cache *iint, int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file, void *buf, loff_t size, struct file *file, void *buf, loff_t size,
...@@ -268,7 +268,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, ...@@ -268,7 +268,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
struct ima_template_desc *template_desc); struct ima_template_desc *template_desc);
void process_buffer_measurement(struct inode *inode, const void *buf, int size, void process_buffer_measurement(struct inode *inode, const void *buf, int size,
const char *eventname, enum ima_hooks func, const char *eventname, enum ima_hooks func,
int pcr, const char *keyring); int pcr, const char *func_data);
void ima_audit_measurement(struct integrity_iint_cache *iint, void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename); const unsigned char *filename);
int ima_alloc_init_template(struct ima_event_data *event_data, int ima_alloc_init_template(struct ima_event_data *event_data,
...@@ -284,7 +284,7 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); ...@@ -284,7 +284,7 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
enum ima_hooks func, int mask, int flags, int *pcr, enum ima_hooks func, int mask, int flags, int *pcr,
struct ima_template_desc **template_desc, struct ima_template_desc **template_desc,
const char *keyring); const char *func_data);
void ima_init_policy(void); void ima_init_policy(void);
void ima_update_policy(void); void ima_update_policy(void);
void ima_update_policy_flag(void); void ima_update_policy_flag(void);
......
...@@ -170,7 +170,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, ...@@ -170,7 +170,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
* @func: caller identifier * @func: caller identifier
* @pcr: pointer filled in if matched measure policy sets pcr= * @pcr: pointer filled in if matched measure policy sets pcr=
* @template_desc: pointer filled in if matched measure policy sets template= * @template_desc: pointer filled in if matched measure policy sets template=
* @keyring: keyring name used to determine the action * @func_data: func specific data, may be NULL
* *
* The policy is defined in terms of keypairs: * The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic= * subj=, obj=, type=, func=, mask=, fsmagic=
...@@ -186,14 +186,14 @@ void ima_add_violation(struct file *file, const unsigned char *filename, ...@@ -186,14 +186,14 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
int mask, enum ima_hooks func, int *pcr, int mask, enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc, struct ima_template_desc **template_desc,
const char *keyring) const char *func_data)
{ {
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag; flags &= ima_policy_flag;
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
template_desc, keyring); template_desc, func_data);
} }
/* /*
......
...@@ -816,13 +816,13 @@ int ima_post_load_data(char *buf, loff_t size, ...@@ -816,13 +816,13 @@ int ima_post_load_data(char *buf, loff_t size,
* @eventname: event name to be used for the buffer entry. * @eventname: event name to be used for the buffer entry.
* @func: IMA hook * @func: IMA hook
* @pcr: pcr to extend the measurement * @pcr: pcr to extend the measurement
* @keyring: keyring name to determine the action to be performed * @func_data: func specific data, may be NULL
* *
* Based on policy, the buffer is measured into the ima log. * Based on policy, the buffer is measured into the ima log.
*/ */
void process_buffer_measurement(struct inode *inode, const void *buf, int size, void process_buffer_measurement(struct inode *inode, const void *buf, int size,
const char *eventname, enum ima_hooks func, const char *eventname, enum ima_hooks func,
int pcr, const char *keyring) int pcr, const char *func_data)
{ {
int ret = 0; int ret = 0;
const char *audit_cause = "ENOMEM"; const char *audit_cause = "ENOMEM";
...@@ -861,7 +861,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, ...@@ -861,7 +861,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
if (func) { if (func) {
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
action = ima_get_action(inode, current_cred(), secid, 0, func, action = ima_get_action(inode, current_cred(), secid, 0, func,
&pcr, &template, keyring); &pcr, &template, func_data);
if (!(action & IMA_MEASURE)) if (!(action & IMA_MEASURE))
return; return;
} }
......
...@@ -453,30 +453,40 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, ...@@ -453,30 +453,40 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
} }
/** /**
* ima_match_keyring - determine whether the keyring matches the measure rule * ima_match_rule_data - determine whether func_data matches the policy rule
* @rule: a pointer to a rule * @rule: a pointer to a rule
* @keyring: name of the keyring to match against the measure rule * @func_data: data to match against the measure rule data
* @cred: a pointer to a credentials structure for user validation * @cred: a pointer to a credentials structure for user validation
* *
* Returns true if keyring matches one in the rule, false otherwise. * Returns true if func_data matches one in the rule, false otherwise.
*/ */
static bool ima_match_keyring(struct ima_rule_entry *rule, static bool ima_match_rule_data(struct ima_rule_entry *rule,
const char *keyring, const struct cred *cred) const char *func_data,
const struct cred *cred)
{ {
const struct ima_rule_opt_list *opt_list = NULL;
bool matched = false; bool matched = false;
size_t i; size_t i;
if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid)) if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
return false; return false;
switch (rule->func) {
case KEY_CHECK:
if (!rule->keyrings) if (!rule->keyrings)
return true; return true;
if (!keyring) opt_list = rule->keyrings;
break;
default:
return false;
}
if (!func_data)
return false; return false;
for (i = 0; i < rule->keyrings->count; i++) { for (i = 0; i < opt_list->count; i++) {
if (!strcmp(rule->keyrings->items[i], keyring)) { if (!strcmp(opt_list->items[i], func_data)) {
matched = true; matched = true;
break; break;
} }
...@@ -493,20 +503,20 @@ static bool ima_match_keyring(struct ima_rule_entry *rule, ...@@ -493,20 +503,20 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
* @secid: the secid of the task to be validated * @secid: the secid of the task to be validated
* @func: LIM hook identifier * @func: LIM hook identifier
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
* @keyring: keyring name to check in policy for KEY_CHECK func * @func_data: func specific data, may be NULL
* *
* Returns true on rule match, false on failure. * Returns true on rule match, false on failure.
*/ */
static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
const struct cred *cred, u32 secid, const struct cred *cred, u32 secid,
enum ima_hooks func, int mask, enum ima_hooks func, int mask,
const char *keyring) const char *func_data)
{ {
int i; int i;
if (func == KEY_CHECK) { if (func == KEY_CHECK) {
return (rule->flags & IMA_FUNC) && (rule->func == func) && return (rule->flags & IMA_FUNC) && (rule->func == func) &&
ima_match_keyring(rule, keyring, cred); ima_match_rule_data(rule, func_data, cred);
} }
if ((rule->flags & IMA_FUNC) && if ((rule->flags & IMA_FUNC) &&
(rule->func != func && func != POST_SETATTR)) (rule->func != func && func != POST_SETATTR))
...@@ -610,8 +620,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) ...@@ -610,8 +620,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
* @pcr: set the pcr to extend * @pcr: set the pcr to extend
* @template_desc: the template that should be used for this rule * @template_desc: the template that should be used for this rule
* @keyring: the keyring name, if given, to be used to check in the policy. * @func_data: func specific data, may be NULL
* keyring can be NULL if func is anything other than KEY_CHECK.
* *
* Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
* conditions. * conditions.
...@@ -623,7 +632,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) ...@@ -623,7 +632,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
enum ima_hooks func, int mask, int flags, int *pcr, enum ima_hooks func, int mask, int flags, int *pcr,
struct ima_template_desc **template_desc, struct ima_template_desc **template_desc,
const char *keyring) const char *func_data)
{ {
struct ima_rule_entry *entry; struct ima_rule_entry *entry;
int action = 0, actmask = flags | (flags << 1); int action = 0, actmask = flags | (flags << 1);
...@@ -638,7 +647,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, ...@@ -638,7 +647,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
continue; continue;
if (!ima_match_rules(entry, inode, cred, secid, func, mask, if (!ima_match_rules(entry, inode, cred, secid, func, mask,
keyring)) func_data))
continue; continue;
action |= entry->flags & IMA_ACTION_FLAGS; action |= entry->flags & IMA_ACTION_FLAGS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment