This list is closed, nobody may subscribe to it.
2007 |
Jan
|
Feb
(10) |
Mar
(26) |
Apr
(8) |
May
(3) |
Jun
|
Jul
(26) |
Aug
(10) |
Sep
|
Oct
|
Nov
(2) |
Dec
(4) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
|
Feb
(13) |
Mar
(4) |
Apr
(3) |
May
(5) |
Jun
|
Jul
(7) |
Aug
(8) |
Sep
(5) |
Oct
(16) |
Nov
|
Dec
(6) |
2009 |
Jan
(2) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
(19) |
Jul
(4) |
Aug
|
Sep
(13) |
Oct
(10) |
Nov
(12) |
Dec
(2) |
2010 |
Jan
|
Feb
(2) |
Mar
(17) |
Apr
(28) |
May
|
Jun
(17) |
Jul
(11) |
Aug
(12) |
Sep
(2) |
Oct
|
Nov
|
Dec
(1) |
2011 |
Jan
|
Feb
|
Mar
(20) |
Apr
(10) |
May
(1) |
Jun
|
Jul
|
Aug
(15) |
Sep
(14) |
Oct
(2) |
Nov
|
Dec
|
2012 |
Jan
(1) |
Feb
(53) |
Mar
(15) |
Apr
(4) |
May
(2) |
Jun
(13) |
Jul
|
Aug
|
Sep
(12) |
Oct
|
Nov
|
Dec
(6) |
2013 |
Jan
(7) |
Feb
(8) |
Mar
(4) |
Apr
(5) |
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
(6) |
Oct
|
Nov
(5) |
Dec
(8) |
2014 |
Jan
(17) |
Feb
(24) |
Mar
(8) |
Apr
(7) |
May
(18) |
Jun
(15) |
Jul
(5) |
Aug
(2) |
Sep
(49) |
Oct
(28) |
Nov
(7) |
Dec
(30) |
2015 |
Jan
(40) |
Feb
|
Mar
(9) |
Apr
(2) |
May
(9) |
Jun
(31) |
Jul
(33) |
Aug
(5) |
Sep
(20) |
Oct
|
Nov
(3) |
Dec
(12) |
2016 |
Jan
(14) |
Feb
(29) |
Mar
(10) |
Apr
(4) |
May
(4) |
Jun
|
Jul
(5) |
Aug
(19) |
Sep
(21) |
Oct
(2) |
Nov
(36) |
Dec
(30) |
2017 |
Jan
(101) |
Feb
(12) |
Mar
(7) |
Apr
(2) |
May
(29) |
Jun
(22) |
Jul
(7) |
Aug
(93) |
Sep
(27) |
Oct
(39) |
Nov
|
Dec
|
From: Magalhaes, G. (B. R&D-CL) <gui...@hp...> - 2017-05-11 14:54:04
|
I would like to replace part of the email below which briefly presents each one of the patches in this series. This is the right summary: -- Patches 1, 2 and 3 qualify the file pathname considering multiple namespaces. Patch 4 adds the namespace securityfs file which is the interface to define IMA policy per namespace. New policy file is created for each namespace and the policy securityfs mechanism is completely reused. Patch 6 adds a hook to fs/namespace.c to automatically delete all namespace IMA policy resources such as radix tree entry and securityfs files. Patches 8 and 9 are small implementation details Patches 5, 7, 10 are the key changes to encapsulate all policy rules and flags in a structure per namespace. The correct structure is retrieved for the target namespace and the namespace rules are used on that context. Patch 11 adds the enforce_ns appraise mode which enables different appraise modes per namespace. -- ---- Guilherme -----Original Message----- From: Magalhaes, Guilherme (Brazil R&D-CL) Sent: quinta-feira, 11 de maio de 2017 11:00 To: dmi...@gm...; zo...@li... Cc: vi...@ze...; jam...@or...; se...@ha...; lin...@vg...; lin...@vg...; lin...@li...; lin...@li...; lin...@vg...; ty...@do...; Souza, Joaquim (Brazil R&D-ECL) <joa...@hp...>; Edwards, Nigel <nig...@hp...>; Magalhaes, Guilherme (Brazil R&D-CL) <gui...@hp...> Subject: [RFC 00/11] ima: namespace support for IMA policy The IMA policy rules and policy/appraise flags are now encapsulated on a new structure which completely describes the policy for a given namespace. The correct namespace structure is retrieved from a radix tree based on the namespace id in use by the process in the context whenever the IMA policy rules or flags are needed. The existent securityfs interface is reused to define policy per namespace. A new namespace file is used to create a folder for a given namespace id with a policy file which can then be used to define rules for that namespace. Patches 1, 2 and 4 qualify the file pathname considering multiple namespaces. Patch 3 adds a new kernel config which enables all the policy per namespace functionality. Patch 5 adds the namespace securityfs file which is the interface to define IMA policy per namespace. New policy file is creanted for each namespace and the policy securityfs mechanism is completely reused. Patche 7 adds a hook to fs/namespace.c to automatically delete all namespace IMA policy resources such as radix tree entry and securityfs files. Patches 8, 10, 11 and 14 are small implementation details Patches 6, 9, 12 are key changes to encapsulate all policy rules and flags in a structure per namespace. The correct structure is retrieved for the target namespace and the namespace rules are used on that context. Patch 13 adds the enforce_ns appraise mode which enables different appraise modes per namespace. Other areas might still need work to completely namespace IMA. For instance, EVM and templates per namespace are not yet covered. Guilherme Magalhaes (11): ima: qualify pathname in audit info record ima: qualify pathname in audit measurement record ima: qualify pathname in measurement file ima: add support to namespace securityfs file ima: store new namespace policy structure in a radix tree ima, fs: release namespace policy resources ima: new namespace policy structure to track initial namespace policy data ima: block initial namespace id on the namespace policy interface ima: delete namespace policy securityfs file in write-once mode ima: handling all policy flags per namespace using ima_ns_policy structure ima: appraise mode per namespace with new enforce_ns appraise mode fs/namespace.c | 4 + include/linux/integrity.h | 9 + security/integrity/ima/Kconfig | 8 + security/integrity/ima/ima.h | 78 ++++- security/integrity/ima/ima_api.c | 14 +- security/integrity/ima/ima_appraise.c | 30 +- security/integrity/ima/ima_fs.c | 454 ++++++++++++++++++++++++++++-- security/integrity/ima/ima_init.c | 13 +- security/integrity/ima/ima_main.c | 40 ++- security/integrity/ima/ima_policy.c | 210 +++++++++++--- security/integrity/ima/ima_template.c | 10 +- security/integrity/ima/ima_template_lib.c | 70 +++++ security/integrity/ima/ima_template_lib.h | 13 + security/integrity/integrity_audit.c | 5 + 14 files changed, 860 insertions(+), 98 deletions(-) -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:16:32
|
Global ima_appraise renamed to ima_appraise_mode and it saves the initial appraise mode. It is used to initialize the ima_appraise ima_ns_policy field when the policy is defined by user the first time for a namespace. New 'enforce_ns' appraise mode created. On this new appraise mode, the initial appraise mode works in 'enforce' mode, but for new namespaces the appraise mode is set to 'fix' until a policy is defined for the new namespace and then the appraise mode is automatically set to 'enforce'. This new mode is useful to keep the initial namespace appraise mode clearly in 'enforce' mode while namespaces can set their appraise modes separatedly. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima.h | 6 +++++- security/integrity/ima/ima_appraise.c | 11 +++++++---- security/integrity/ima/ima_fs.c | 7 ++++++- security/integrity/ima/ima_main.c | 4 ++-- security/integrity/ima/ima_policy.c | 13 +++++++++++-- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index fd5cfe9..9d451fd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -65,7 +65,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; extern int ima_initialized; extern int ima_used_chip; extern int ima_hash_algo; -extern int ima_appraise; +extern int ima_appraise_mode; /* IMA event related data */ struct ima_event_data { @@ -278,6 +278,10 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_MODULES 0x08 #define IMA_APPRAISE_FIRMWARE 0x10 #define IMA_APPRAISE_POLICY 0x20 +#ifdef CONFIG_IMA_PER_NAMESPACE +#define IMA_APPRAISE_NAMESPACE 0x40 +#define IMA_APPRAISE_ENFORCE_NS (IMA_APPRAISE_ENFORCE | IMA_APPRAISE_NAMESPACE) +#endif #ifdef CONFIG_IMA_APPRAISE diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 510bb2f..4b94c2a 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -21,12 +21,15 @@ static int __init default_appraise_setup(char *str) { if (strncmp(str, "off", 3) == 0) - ima_appraise = 0; + ima_appraise_mode = 0; else if (strncmp(str, "log", 3) == 0) - ima_appraise = IMA_APPRAISE_LOG; + ima_appraise_mode = IMA_APPRAISE_LOG; else if (strncmp(str, "fix", 3) == 0) - ima_appraise = IMA_APPRAISE_FIX; - + ima_appraise_mode = IMA_APPRAISE_FIX; +#ifdef CONFIG_IMA_PER_NAMESPACE + else if (strncmp(str, "enforce_ns", 10) == 0) + ima_appraise_mode = IMA_APPRAISE_ENFORCE_NS; +#endif return 1; } diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index bc18722..91cafb5 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -308,7 +308,12 @@ static int allocate_namespace_policy(struct ima_ns_policy **ins, p->policy_dentry = policy_dentry; p->ns_dentry = ns_dentry; - p->ima_appraise = ima_appraise; + if (ima_appraise_mode == IMA_APPRAISE_ENFORCE_NS) + /* For now, on the enforce_ns mode, a new namespace starts in + * fix mode */ + p->ima_appraise = IMA_APPRAISE_FIX; + else + p->ima_appraise = ima_appraise_mode; p->ima_policy_flag = 0; INIT_LIST_HEAD(&p->ima_policy_rules); /* namespace starts with empty rules and not pointing to diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 1b995bb..1938c74 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -31,9 +31,9 @@ int ima_initialized; #ifdef CONFIG_IMA_APPRAISE /* Used during IMA initialization only */ -int ima_appraise = IMA_APPRAISE_ENFORCE; +int ima_appraise_mode = IMA_APPRAISE_ENFORCE; #else -int ima_appraise; +int ima_appraise_mode; #endif int ima_hash_algo = HASH_ALGO_SHA1; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4ffb4ad..bd67a08 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -517,7 +517,7 @@ void __init ima_init_policy(void) ins = &ima_initial_namespace_policy; ins->ima_rules = &ima_default_rules; - ins->ima_appraise = ima_appraise; + ins->ima_appraise = ima_appraise_mode; ima_update_policy_flag(ins); temp_ima_appraise = 0; @@ -564,7 +564,16 @@ void ima_update_policy(struct ima_ns_policy *ins) if (ins->ima_rules != policy) { ins->ima_policy_flag = 0; ins->ima_rules = policy; - ins->ima_appraise = ima_appraise; + ins->ima_appraise = ima_appraise_mode; +#ifdef CONFIG_IMA_PER_NAMESPACE + if (ins != &ima_initial_namespace_policy && + ima_appraise_mode == IMA_APPRAISE_ENFORCE_NS) { + /* For now, on the enforce_ns mode, switch to enforce mode + * when new policy is set for a namespace and for the first + * time */ + ins->ima_appraise = IMA_APPRAISE_ENFORCE; + } +#endif } ima_update_policy_flag(ins); -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:35
|
Global ima_appraise still saves the initial appraise mode and it is used to initialize namespace.ima_appraise flag when a user defined policy is set. Globals moved into ima_ns_policy structure (namespace IMA policy private data): - ima_policy_flag - ima_appraise - ima_rules - ima_policy_rules Functions changed to take as parameter the correct ima_ns_policy structure. ima_initial_namespace_policy is initialized in ima_init_policy and stores the initial namespace IMA policy data. Replacing direct uses of ima_ns_policy lock with the ima_namespace_lock() and ima_namespace_unlock() functions. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima.h | 17 +++--- security/integrity/ima/ima_api.c | 6 +- security/integrity/ima/ima_appraise.c | 21 +++++-- security/integrity/ima/ima_fs.c | 26 ++++++--- security/integrity/ima/ima_init.c | 11 +++- security/integrity/ima/ima_main.c | 36 ++++++++---- security/integrity/ima/ima_policy.c | 100 +++++++++++++++++++++++++--------- 7 files changed, 150 insertions(+), 67 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 20b927e..fd5cfe9 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -61,9 +61,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; #endif -/* current content of the policy */ -extern int ima_policy_flag; - /* set during initialization */ extern int ima_initialized; extern int ima_used_chip; @@ -149,7 +146,6 @@ struct ima_ns_policy { int ima_policy_flag; int ima_appraise; }; - extern struct ima_ns_policy ima_initial_namespace_policy; #ifdef CONFIG_IMA_PER_NAMESPACE extern spinlock_t ima_ns_policy_lock; @@ -241,7 +237,7 @@ enum ima_hooks { /* LIM API function definitions */ int ima_get_action(struct inode *inode, int mask, - enum ima_hooks func, int *pcr); + enum ima_hooks func, int *pcr, struct ima_ns_policy *ins); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file, void *buf, loff_t size, @@ -262,10 +258,10 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); /* IMA policy related functions */ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, - int flags, int *pcr); + int flags, int *pcr, struct ima_ns_policy *ins); void ima_init_policy(void); -void ima_update_policy(void); -void ima_update_policy_flag(void); +void ima_update_policy(struct ima_ns_policy *ins); +void ima_update_policy_flag(struct ima_ns_policy *ins); ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); void ima_free_policy_rules(struct list_head *policy_rules); @@ -283,12 +279,13 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_FIRMWARE 0x10 #define IMA_APPRAISE_POLICY 0x20 + #ifdef CONFIG_IMA_APPRAISE int ima_appraise_measurement(enum ima_hooks func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, - int xattr_len, int opened); + int xattr_len, int opened, struct ima_ns_policy *ins); int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, @@ -304,7 +301,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, - int xattr_len, int opened) + int xattr_len, int opened, struct ima_ns_policy *ins) { return INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b05c1fd..9aba542 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -173,13 +173,13 @@ void ima_add_violation(struct file *file, const unsigned char *filename, * Returns IMA_MEASURE, IMA_APPRAISE mask. * */ -int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr) +int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr, struct ima_ns_policy *ins) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE; - flags &= ima_policy_flag; + flags &= ins->ima_policy_flag; - return ima_match_policy(inode, func, mask, flags, pcr); + return ima_match_policy(inode, func, mask, flags, pcr, ins); } /* diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 1fd9539..510bb2f 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -26,6 +26,7 @@ static int __init default_appraise_setup(char *str) ima_appraise = IMA_APPRAISE_LOG; else if (strncmp(str, "fix", 3) == 0) ima_appraise = IMA_APPRAISE_FIX; + return 1; } @@ -38,10 +39,12 @@ __setup("ima_appraise=", default_appraise_setup); */ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) { - if (!ima_appraise) + struct ima_ns_policy *ins = ima_get_current_namespace_policy(); + + if (!ins->ima_appraise) return 0; - return ima_match_policy(inode, func, mask, IMA_APPRAISE, NULL); + return ima_match_policy(inode, func, mask, IMA_APPRAISE, NULL, ins); } static int ima_fix_xattr(struct dentry *dentry, @@ -189,7 +192,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, - int xattr_len, int opened) + int xattr_len, int opened, struct ima_ns_policy *ins) { static const char op[] = "appraise_data"; char *cause = "unknown"; @@ -273,7 +276,7 @@ int ima_appraise_measurement(enum ima_hooks func, out: if (status != INTEGRITY_PASS) { - if ((ima_appraise & IMA_APPRAISE_FIX) && + if ((ins->ima_appraise & IMA_APPRAISE_FIX) && (!xattr_value || xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { if (!ima_fix_xattr(dentry, iint)) @@ -326,8 +329,11 @@ void ima_inode_post_setattr(struct dentry *dentry) struct inode *inode = d_backing_inode(dentry); struct integrity_iint_cache *iint; int must_appraise; + struct ima_ns_policy *ins; - if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) + ins = ima_get_current_namespace_policy(); + + if (!(ins->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) || !(inode->i_opflags & IOP_XATTR)) return; @@ -363,8 +369,11 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, static void ima_reset_appraise_flags(struct inode *inode, int digsig) { struct integrity_iint_cache *iint; + struct ima_ns_policy *ins; + + ins = ima_get_current_namespace_policy(); - if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) + if (!(ins->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return; iint = integrity_iint_find(inode); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 94e89fe..bc18722 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -308,7 +308,7 @@ static int allocate_namespace_policy(struct ima_ns_policy **ins, p->policy_dentry = policy_dentry; p->ns_dentry = ns_dentry; - p->ima_appraise = 0; + p->ima_appraise = ima_appraise; p->ima_policy_flag = 0; INIT_LIST_HEAD(&p->ima_policy_rules); /* namespace starts with empty rules and not pointing to @@ -488,6 +488,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, { char *data; ssize_t result; + struct ima_ns_policy *ins; if (datalen >= PAGE_SIZE) datalen = PAGE_SIZE - 1; @@ -512,19 +513,30 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (result < 0) goto out_free; + ima_namespace_lock(); + ins = ima_get_namespace_policy_from_inode(file->f_inode); + if (!ins) { + /* the namespace is not valid anymore, indicate the error + * and exit */ + result = -EINVAL; + goto out_unlock; + } + if (data[0] == '/') { result = ima_read_policy(data); - } else if (ima_appraise & IMA_APPRAISE_POLICY) { + } else if (ins->ima_appraise & IMA_APPRAISE_POLICY) { pr_err("IMA: signed policy file (specified as an absolute pathname) required\n"); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, "policy_update", "signed policy required", 1, 0); - if (ima_appraise & IMA_APPRAISE_ENFORCE) + if (ins->ima_appraise & IMA_APPRAISE_ENFORCE) result = -EACCES; } else { result = ima_parse_add_rule(data); } +out_unlock: + ima_namespace_unlock(); mutex_unlock(&ima_write_mutex); out_free: kfree(data); @@ -611,7 +623,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) return 0; } - ima_update_policy(); + ima_update_policy(ins); #ifndef CONFIG_IMA_WRITE_POLICY if (ins == &ima_initial_namespace_policy) { securityfs_remove(ima_policy_initial_ns); @@ -698,16 +710,16 @@ void ima_mnt_namespace_dying(unsigned int ns_id) { struct ima_ns_policy *p; - spin_lock(&ima_ns_policy_lock); + ima_namespace_lock(); p = radix_tree_delete(&ima_ns_policy_mapping, ns_id); if (!p) { - spin_unlock(&ima_ns_policy_lock); + ima_namespace_unlock(); return; } free_namespace_policy(p); - spin_unlock(&ima_ns_policy_lock); + ima_namespace_unlock(); } static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b557ee3..f0bb196 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -96,11 +96,16 @@ static int __init ima_add_boot_aggregate(void) #ifdef CONFIG_IMA_LOAD_X509 void __init ima_load_x509(void) { - int unset_flags = ima_policy_flag & IMA_APPRAISE; + int unset_flags; + struct ima_ns_policy *ins; - ima_policy_flag &= ~unset_flags; + ins = ima_get_current_namespace_policy(); + + unset_flags = ins->ima_policy_flag & IMA_APPRAISE; + + ins->ima_policy_flag &= ~unset_flags; integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH); - ima_policy_flag |= unset_flags; + ins->ima_policy_flag |= unset_flags; } #endif diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2aebb79..1b995bb 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -30,6 +30,7 @@ int ima_initialized; #ifdef CONFIG_IMA_APPRAISE +/* Used during IMA initialization only */ int ima_appraise = IMA_APPRAISE_ENFORCE; #else int ima_appraise; @@ -144,9 +145,13 @@ void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; + struct ima_ns_policy *ins; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + ins = ima_get_current_namespace_policy(); + + if (!ins->ima_policy_flag || !S_ISREG(inode->i_mode)) { return; + } iint = integrity_iint_find(inode); if (!iint) @@ -170,17 +175,20 @@ static int process_measurement(struct file *file, char *buf, loff_t size, int xattr_len = 0; bool violation_check; enum hash_algo hash_algo; + struct ima_ns_policy *ins; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + ins = ima_get_current_namespace_policy(); + + if (!ins->ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action * bitmask based on the appraise/audit/measurement policy. * Included is the appraise submask. */ - action = ima_get_action(inode, mask, func, &pcr); + action = ima_get_action(inode, mask, func, &pcr, ins); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && - (ima_policy_flag & IMA_MEASURE)); + (ins->ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0; @@ -249,7 +257,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size, xattr_value, xattr_len, pcr); if (action & IMA_APPRAISE_SUBMASK) rc = ima_appraise_measurement(func, iint, file, pathname, - xattr_value, xattr_len, opened); + xattr_value, xattr_len, opened, ins); if (action & IMA_AUDIT) ima_audit_measurement(iint, pathname); @@ -263,7 +271,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size, __putname(pathbuf); out: inode_unlock(inode); - if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) + if ((rc && must_appraise) && (ins->ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; return 0; } @@ -361,8 +369,10 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) { if (!file && read_id == READING_MODULE) { #ifndef CONFIG_MODULE_SIG_FORCE - if ((ima_appraise & IMA_APPRAISE_MODULES) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) + struct ima_ns_policy *ins; + ins = ima_get_current_namespace_policy(); + if ((ins->ima_appraise & IMA_APPRAISE_MODULES) && + (ins->ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; /* INTEGRITY_UNKNOWN */ #endif return 0; /* We rely on module signature checking */ @@ -395,10 +405,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id read_id) { enum ima_hooks func; + struct ima_ns_policy *ins; + + ins = ima_get_current_namespace_policy(); if (!file && read_id == READING_FIRMWARE) { - if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) + if ((ins->ima_appraise & IMA_APPRAISE_FIRMWARE) && + (ins->ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; /* INTEGRITY_UNKNOWN */ return 0; } @@ -407,7 +420,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, return 0; if (!file || !buf || size == 0) { /* should never happen */ - if (ima_appraise & IMA_APPRAISE_ENFORCE) + if (ins->ima_appraise & IMA_APPRAISE_ENFORCE) return -EACCES; return 0; } @@ -425,7 +438,6 @@ static int __init init_ima(void) error = ima_init(); if (!error) { ima_initialized = 1; - ima_update_policy_flag(); } return error; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8c0d4c9..4ffb4ad 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -46,7 +46,7 @@ #define INVALID_PCR(a) (((a) < 0) || \ (a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8)) -int ima_policy_flag; +/* used only during policy initialization and policy change */ static int temp_ima_appraise; #ifdef CONFIG_IMA_PER_NAMESPACE @@ -66,6 +66,7 @@ struct ima_ns_policy ima_initial_namespace_policy = { .ima_appraise = 0 }; + #define MAX_LSM_RULES 6 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE @@ -166,11 +167,12 @@ static struct ima_rule_entry default_appraise_rules[] = { #endif }; +/* used only during policy setup of the initial namespace */ static LIST_HEAD(ima_default_rules); -static LIST_HEAD(ima_policy_rules); +/* used during policy setting and cleaned up for the next policy setting */ static LIST_HEAD(ima_temp_rules); -static struct list_head *ima_rules; +/* only used during setup of the initial namespace policy */ static int ima_policy __initdata; static int __init default_measure_policy_setup(char *str) @@ -268,13 +270,14 @@ struct ima_ns_policy *ima_get_current_namespace_policy(void) * the reloaded LSM policy. We assume the rules still exist; and BUG_ON() if * they don't. */ -static void ima_lsm_update_rules(void) +static void ima_lsm_update_rules(struct ima_ns_policy *ins) { struct ima_rule_entry *entry; int result; int i; - list_for_each_entry(entry, &ima_policy_rules, list) { + rcu_read_lock(); + list_for_each_entry_rcu(entry, &ins->ima_policy_rules, list) { for (i = 0; i < MAX_LSM_RULES; i++) { if (!entry->lsm[i].rule) continue; @@ -285,6 +288,7 @@ static void ima_lsm_update_rules(void) BUG_ON(!entry->lsm[i].rule); } } + rcu_read_unlock(); } /** @@ -297,7 +301,7 @@ static void ima_lsm_update_rules(void) * Returns true on rule match, false on failure. */ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, - enum ima_hooks func, int mask) + enum ima_hooks func, int mask, struct ima_ns_policy *ins) { struct task_struct *tsk = current; const struct cred *cred = current_cred(); @@ -365,7 +369,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, } if ((rc < 0) && (!retried)) { retried = 1; - ima_lsm_update_rules(); + ima_lsm_update_rules(ins); goto retry; } if (!rc) @@ -412,18 +416,18 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * than writes so ima_match_policy() is classical RCU candidate. */ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, - int flags, int *pcr) + int flags, int *pcr, struct ima_ns_policy *ins) { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_rules, list) { + list_for_each_entry_rcu(entry, ins->ima_rules, list) { if (!(entry->action & actmask)) continue; - if (!ima_match_rules(entry, inode, func, mask)) + if (!ima_match_rules(entry, inode, func, mask, ins)) continue; action |= entry->flags & IMA_ACTION_FLAGS; @@ -454,18 +458,20 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, * out of a function or not call the function in the first place * can be made earlier. */ -void ima_update_policy_flag(void) +void ima_update_policy_flag(struct ima_ns_policy *ins) { struct ima_rule_entry *entry; - list_for_each_entry(entry, ima_rules, list) { + rcu_read_lock(); + list_for_each_entry_rcu(entry, ins->ima_rules, list) { if (entry->action & IMA_DO_MASK) - ima_policy_flag |= entry->action; + ins->ima_policy_flag |= entry->action; } + rcu_read_unlock(); - ima_appraise |= temp_ima_appraise; - if (!ima_appraise) - ima_policy_flag &= ~IMA_APPRAISE; + ins->ima_appraise |= temp_ima_appraise; + if (!ins->ima_appraise) + ins->ima_policy_flag &= ~IMA_APPRAISE; } /** @@ -477,6 +483,7 @@ void ima_update_policy_flag(void) void __init ima_init_policy(void) { int i, measure_entries, appraise_entries; + struct ima_ns_policy *ins; /* if !ima_policy set entries = 0 so we load NO default rules */ measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0; @@ -507,8 +514,13 @@ void __init ima_init_policy(void) temp_ima_appraise |= IMA_APPRAISE_POLICY; } - ima_rules = &ima_default_rules; - ima_update_policy_flag(); + ins = &ima_initial_namespace_policy; + + ins->ima_rules = &ima_default_rules; + ins->ima_appraise = ima_appraise; + + ima_update_policy_flag(ins); + temp_ima_appraise = 0; } /* Make sure we have a valid policy, at least containing some rules. */ @@ -530,14 +542,14 @@ int ima_check_policy(void) * Policy rules are never deleted so ima_policy_flag gets zeroed only once when * we switch from the default policy to user defined. */ -void ima_update_policy(void) +void ima_update_policy(struct ima_ns_policy *ins) { struct list_head *first, *last, *policy; /* append current policy with the new rules */ first = (&ima_temp_rules)->next; last = (&ima_temp_rules)->prev; - policy = &ima_policy_rules; + policy = &ins->ima_policy_rules; synchronize_rcu(); @@ -549,11 +561,14 @@ void ima_update_policy(void) /* prepare for the next policy rules addition */ INIT_LIST_HEAD(&ima_temp_rules); - if (ima_rules != policy) { - ima_policy_flag = 0; - ima_rules = policy; + if (ins->ima_rules != policy) { + ins->ima_policy_flag = 0; + ins->ima_rules = policy; + ins->ima_appraise = ima_appraise; } - ima_update_policy_flag(); + + ima_update_policy_flag(ins); + temp_ima_appraise = 0; } enum { @@ -964,6 +979,7 @@ void ima_free_policy_rules(struct list_head *policy_rules) void ima_delete_rules(void) { temp_ima_appraise = 0; + ima_free_policy_rules(&ima_temp_rules); } @@ -1002,28 +1018,49 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) { loff_t l = *pos; struct ima_rule_entry *entry; + struct ima_ns_policy *ins; + + ima_namespace_lock(); + ins = ima_get_namespace_policy_from_inode(m->file->f_inode); + if (!ins) { + ima_namespace_unlock(); + return NULL; + } rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_rules, list) { + list_for_each_entry_rcu(entry, ins->ima_rules, list) { if (!l--) { rcu_read_unlock(); + ima_namespace_unlock(); return entry; } } rcu_read_unlock(); + ima_namespace_unlock(); return NULL; } void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) { struct ima_rule_entry *entry = v; + struct ima_ns_policy *ins; + void *p; + + ima_namespace_lock(); + ins = ima_get_namespace_policy_from_inode(m->file->f_inode); + if (!ins) { + ima_namespace_unlock(); + return NULL; + } rcu_read_lock(); entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list); rcu_read_unlock(); (*pos)++; - return (&entry->list == ima_rules) ? NULL : entry; + p = (&entry->list == ins->ima_rules) ? NULL : entry; + ima_namespace_unlock(); + return p; } void ima_policy_stop(struct seq_file *m, void *v) @@ -1082,6 +1119,16 @@ int ima_policy_show(struct seq_file *m, void *v) struct ima_rule_entry *entry = v; int i; char tbuf[64] = {0,}; + struct ima_ns_policy *ins; + + ima_namespace_lock(); + ins = ima_get_namespace_policy_from_inode(m->file->f_inode); + if (!ins) { + /* this namespace was release and the policy entry is not valid + * anymore */ + ima_namespace_unlock(); + return 0; + } rcu_read_lock(); @@ -1184,6 +1231,7 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, "permit_directio "); rcu_read_unlock(); seq_puts(m, "\n"); + ima_namespace_unlock(); return 0; } #endif /* CONFIG_IMA_READ_POLICY */ -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:22
|
When policy file is written and write-once is enabled, the policy file must be deleted. Select the namespace policy structure to get the correct policy file descriptor. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima_fs.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 65c43e7..94e89fe 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -575,6 +575,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) static int ima_release_policy(struct inode *inode, struct file *file) { const char *cause = valid_policy ? "completed" : "failed"; + struct ima_ns_policy *ins; if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); @@ -595,15 +596,37 @@ static int ima_release_policy(struct inode *inode, struct file *file) return 0; } + /* get the namespace id from file->inode (policy file inode). + * We also need to synchronize this operation with concurrent namespace + * releasing. */ + ima_namespace_lock(); + ins = ima_get_namespace_policy_from_inode(inode); + if (!ins) { + /* the namespace is not valid anymore, discard new policy + * rules and exit */ + ima_delete_rules(); + valid_policy = 1; + clear_bit(IMA_FS_BUSY, &ima_fs_flags); + ima_namespace_unlock(); + return 0; + } + ima_update_policy(); #ifndef CONFIG_IMA_WRITE_POLICY - securityfs_remove(ima_policy_initial_ns); - ima_policy = NULL; + if (ins == &ima_initial_namespace_policy) { + securityfs_remove(ima_policy_initial_ns); + ima_policy_initial_ns = NULL; + } else { + securityfs_remove(ins->policy_dentry); + ins->policy_dentry = NULL; + } #endif /* always clear the busy flag so other namespaces can use it */ clear_bit(IMA_FS_BUSY, &ima_fs_flags); + ima_namespace_unlock(); + return 0; } -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:22
|
The initial namespace policy is set through the existent interface in the ima/policy securityfs file. Block the initial namespace id when it is written to the ima/namespace securityfs file. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima_fs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 61f8da1..65c43e7 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -365,6 +365,16 @@ static int check_mntns(unsigned int ns_id) return result; } +static unsigned int initial_mntns_id; +static void get_initial_mntns_id(void) +{ + struct ns_common *ns; + + ns = mntns_operations.get(&init_task); + initial_mntns_id = ns->inum; + mntns_operations.put(ns); +} + /* * ima_find_namespace_id_from_inode * @policy_inode: the inode of the securityfs policy file for a given @@ -699,6 +709,12 @@ static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) goto out; } + if (ns_id == initial_mntns_id) { + pr_err("IMA: invalid use of the initial mount namespace\n"); + result = -EINVAL; + goto out; + } + ima_namespace_lock(); if (check_mntns(ns_id)) { result = -ENOENT; @@ -835,6 +851,8 @@ int __init ima_fs_init(void) &ima_namespaces_ops); if (IS_ERR(ima_namespaces)) goto out; + + get_initial_mntns_id(); #endif return 0; -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:15
|
Adding the global ima_initial_namespace_policy which will be used when the initial namespace IMA policy data must be referred or when CONFIG_IMA_PER_NAMESPACE is not defined. New functions which will be used to retrieve the correct namespace IMA policy data from the radix tree map or from the ima_initial_namespace_policy. If the given namespace has not yet defined a private IMA policy, the IMA policy for that namespace falls back to the initial IMA policy by using ima_initial_namespace_policy. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima.h | 6 ++ security/integrity/ima/ima_fs.c | 112 +++++++++++++++++++++++++++++------- security/integrity/ima/ima_policy.c | 72 +++++++++++++++++++++++ 3 files changed, 170 insertions(+), 20 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 1c5c875..20b927e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -150,6 +150,7 @@ struct ima_ns_policy { int ima_appraise; }; +extern struct ima_ns_policy ima_initial_namespace_policy; #ifdef CONFIG_IMA_PER_NAMESPACE extern spinlock_t ima_ns_policy_lock; extern struct radix_tree_root ima_ns_policy_mapping; @@ -203,6 +204,11 @@ static inline void ima_namespace_unlock(void) { } #endif +/* IMA namespace function definitions */ +struct ima_ns_policy *ima_get_current_namespace_policy(void); +struct ima_ns_policy *ima_get_namespace_policy_from_inode(struct inode *inode); +struct ima_ns_policy *ima_get_policy_from_namespace(unsigned int ns_id); + /* * used to protect h_table and sha_table */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 56ba0ff..61f8da1 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -274,6 +274,22 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, }; +static struct dentry *ima_dir; +static struct dentry *binary_runtime_measurements; +static struct dentry *ascii_runtime_measurements; +static struct dentry *runtime_measurements_count; +static struct dentry *violations; +static struct dentry *ima_policy_initial_ns; +#ifdef CONFIG_IMA_PER_NAMESPACE +static struct dentry *ima_namespaces; +#endif + +enum ima_fs_flags { + IMA_FS_BUSY, +}; + +static unsigned long ima_fs_flags; + #ifdef CONFIG_IMA_PER_NAMESPACE /* used for namespace policy rules initialization */ static LIST_HEAD(empty_policy); @@ -348,6 +364,76 @@ static int check_mntns(unsigned int ns_id) return result; } + +/* + * ima_find_namespace_id_from_inode + * @policy_inode: the inode of the securityfs policy file for a given + * namespace + * + * Return 0 if the namespace id is not found in ima_ns_policy_mapping + */ +static unsigned int find_namespace_id_from_inode(struct inode *policy_inode) +{ + unsigned int ns_id = 0; +#ifdef CONFIG_IMA_PER_NAMESPACE + struct ima_ns_policy *ins; + void **slot; + struct radix_tree_iter iter; + + rcu_read_lock(); + radix_tree_for_each_slot(slot, &ima_ns_policy_mapping, &iter, 0) { + ins = radix_tree_deref_slot(slot); + if (unlikely(!ins)) + continue; + if (radix_tree_deref_retry(ins)) { + slot = radix_tree_iter_retry(&iter); + continue; + } + + if (ins->policy_dentry && ins->policy_dentry->d_inode == policy_inode) { + ns_id = iter.index; + break; + } + } + rcu_read_unlock(); +#endif + + return ns_id; +} + +/* + * get_namespace_policy_from_inode - Finds namespace mapping from + * securityfs policy file + * It is called to get the namespace policy reference when a seurityfs + * file such as the namespace or policy files are read or written. + * @inode: inode of the securityfs policy file under a namespace + * folder + * Expects the ima_ns_policy_lock already held + * + * Returns NULL if the namespace policy reference is not reliable once it + * probably was already released after a concurrent namespace release. + * Otherwise, the namespace policy reference is returned. + */ +struct ima_ns_policy *ima_get_namespace_policy_from_inode(struct inode *inode) +{ + unsigned int ns_id; + struct ima_ns_policy *ins; + + ns_id = find_namespace_id_from_inode(inode); +#ifdef CONFIG_IMA_PER_NAMESPACE + if (ns_id == 0 && + (!ima_policy_initial_ns || inode != ima_policy_initial_ns->d_inode)) { + /* ns_id == 0 refers to initial namespace, but inode refers to a + * namespaced policy file. It might be a race condition with + * namespace release, return invalid reference. */ + return NULL; + } +#endif + + ins = ima_get_policy_from_namespace(ns_id); + + return ins; +} #endif static ssize_t ima_read_policy(char *path) @@ -439,22 +525,6 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, return result; } -static struct dentry *ima_dir; -static struct dentry *binary_runtime_measurements; -static struct dentry *ascii_runtime_measurements; -static struct dentry *runtime_measurements_count; -static struct dentry *violations; -static struct dentry *ima_policy; -#ifdef CONFIG_IMA_PER_NAMESPACE -static struct dentry *ima_namespaces; -#endif - -enum ima_fs_flags { - IMA_FS_BUSY, -}; - -static unsigned long ima_fs_flags; - #ifdef CONFIG_IMA_READ_POLICY static const struct seq_operations ima_policy_seqops = { .start = ima_policy_start, @@ -517,7 +587,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) ima_update_policy(); #ifndef CONFIG_IMA_WRITE_POLICY - securityfs_remove(ima_policy); + securityfs_remove(ima_policy_initial_ns); ima_policy = NULL; #endif @@ -539,6 +609,8 @@ static const struct file_operations ima_measure_policy_ops = { /* * Assumes namespace id is in use by some process and this mapping * does not exist in the map table. + * @ns_id namespace id + * Expects ima_ns_policy_lock already held */ static int create_mnt_ns_directory(unsigned int ns_id) { @@ -751,10 +823,10 @@ int __init ima_fs_init(void) if (IS_ERR(violations)) goto out; - ima_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS, + ima_policy_initial_ns = securityfs_create_file("policy", POLICY_FILE_FLAGS, ima_dir, NULL, &ima_measure_policy_ops); - if (IS_ERR(ima_policy)) + if (IS_ERR(ima_policy_initial_ns)) goto out; #ifdef CONFIG_IMA_PER_NAMESPACE @@ -772,7 +844,7 @@ int __init ima_fs_init(void) securityfs_remove(ascii_runtime_measurements); securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_dir); - securityfs_remove(ima_policy); + securityfs_remove(ima_policy_initial_ns); #ifdef CONFIG_IMA_PER_NAMESPACE securityfs_remove(ima_namespaces); #endif diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 2e8c3b7..8c0d4c9 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -20,6 +20,8 @@ #include <linux/rculist.h> #include <linux/genhd.h> #include <linux/seq_file.h> +#include <linux/radix-tree.h> +#include <linux/proc_ns.h> #include "ima.h" @@ -53,6 +55,17 @@ RADIX_TREE(ima_ns_policy_mapping, GFP_ATOMIC); spinlock_t ima_ns_policy_lock; #endif +/* initial namespace map entry, not added to the ima_ns_policy_mapping + * Used as policy fallback for namespaces without policy settings */ +struct ima_ns_policy ima_initial_namespace_policy = { + .policy_dentry = NULL, + .ns_dentry = NULL, + .ima_rules = NULL, + .ima_policy_rules = LIST_HEAD_INIT(ima_initial_namespace_policy.ima_policy_rules), + .ima_policy_flag = 0, + .ima_appraise = 0 + }; + #define MAX_LSM_RULES 6 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE @@ -191,6 +204,65 @@ static int __init default_appraise_policy_setup(char *str) __setup("ima_appraise_tcb", default_appraise_policy_setup); /* + * ima_get_policy_from_namespace - Finds the ns_id mapping to namespace + * policy structure + * @ns_id: mount namespace id to look for in the policy mapping tree + * + * Returns either the given namespace policy data if mapped or the initial + * namespace data instead. + * + * Note that if a namespace has not a specific policy defined, it will + * fall back to the initial namespace policy. + */ +struct ima_ns_policy *ima_get_policy_from_namespace(unsigned int ns_id) +{ + struct ima_ns_policy *ins; + +#ifdef CONFIG_IMA_PER_NAMESPACE + rcu_read_lock(); + ins = radix_tree_lookup(&ima_ns_policy_mapping, ns_id); + rcu_read_unlock(); + + if (!ins) { + ins = &ima_initial_namespace_policy; + } +#else + ins = &ima_initial_namespace_policy; +#endif + + return ins; +} + +/* + * ima_get_current_namespace_policy - Finds the namespace policy mapping + * for the current task + * This function is called on the context of a syscall and then the namespace + * in use will not be released during this context. + */ +struct ima_ns_policy *ima_get_current_namespace_policy(void) +{ + struct ima_ns_policy *ins = NULL; +#ifdef CONFIG_IMA_PER_NAMESPACE + struct ns_common *ns; + + ns = mntns_operations.get(current); + if (ns) { + ins = ima_get_policy_from_namespace(ns->inum); + mntns_operations.put(ns); + } + if (!ins || (ins->ima_rules != &ins->ima_policy_rules)) { + /* if current namespace has no IMA policy, get the + * initial namespace policy */ + ins = &ima_initial_namespace_policy; + } +#else + ins = &ima_initial_namespace_policy; +#endif + + return ins; +} + +/* * The LSM policy can be reloaded, leaving the IMA LSM based rules referring * to the old, stale LSM policy. Update the IMA LSM based rules to reflect * the reloaded LSM policy. We assume the rules still exist; and BUG_ON() if -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:13
|
Creating the namespace securityfs file under ima folder. When a mount namespace id is written to the namespace file, a new folder is created and with a policy file for that specified namespace. Then, user defined policy for namespaces may be set by writing rules to this namespace policy file. With this interface, there is no need to give visibility for the securityfs inside mount namespaces or containers in userspace. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_fs.c | 183 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 42fb91ba..6e8ca8e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -326,4 +326,8 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, #define POLICY_FILE_FLAGS S_IWUSR #endif /* CONFIG_IMA_WRITE_POLICY */ +#ifdef CONFIG_IMA_PER_NAMESPACE +#define NAMESPACES_FILE_FLAGS S_IWUSR +#endif + #endif /* __LINUX_IMA_H */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ca303e5..6456407 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -23,6 +23,8 @@ #include <linux/rcupdate.h> #include <linux/parser.h> #include <linux/vmalloc.h> +#include <linux/proc_ns.h> +#include <linux/radix-tree.h> #include "ima.h" @@ -272,6 +274,40 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, }; +#ifdef CONFIG_IMA_PER_NAMESPACE +/* + * check_mntns: check a mount namespace is valid + * + * @ns_id: namespace id to be checked + * Returns 0 if the namespace is valid. + * + * Note: a better way to implement this check is needed. There are + * cases where the namespace id is valid but not in use by any process + * and then this implementation misses this case. Could we use an + * interface similar to what setns implements? + */ +static int check_mntns(unsigned int ns_id) +{ + struct task_struct *p; + int result = 1; + struct ns_common *ns; + + rcu_read_lock(); + for_each_process(p) { + ns = mntns_operations.get(p); + if (ns->inum == ns_id) { + result = 0; + mntns_operations.put(ns); + break; + } + mntns_operations.put(ns); + } + rcu_read_unlock(); + + return result; +} +#endif + static ssize_t ima_read_policy(char *path) { void *data; @@ -366,6 +402,9 @@ static struct dentry *ascii_runtime_measurements; static struct dentry *runtime_measurements_count; static struct dentry *violations; static struct dentry *ima_policy; +#ifdef CONFIG_IMA_PER_NAMESPACE +static struct dentry *ima_namespaces; +#endif enum ima_fs_flags { IMA_FS_BUSY, @@ -451,6 +490,139 @@ static const struct file_operations ima_measure_policy_ops = { .llseek = generic_file_llseek, }; +#ifdef CONFIG_IMA_PER_NAMESPACE +/* + * Assumes namespace id is in use by some process and this mapping + * does not exist in the map table. + */ +static int create_mnt_ns_directory(unsigned int ns_id) +{ + int result; + struct dentry *ns_dir, *ns_policy; + char dir_name[64]; + + snprintf(dir_name, sizeof(dir_name), "%u", ns_id); + + ns_dir = securityfs_create_dir(dir_name, ima_dir); + if (IS_ERR(ns_dir)) { + result = PTR_ERR(ns_dir); + goto out; + } + + ns_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS, + ns_dir, NULL, + &ima_measure_policy_ops); + if (IS_ERR(ns_policy)) { + result = PTR_ERR(ns_policy); + securityfs_remove(ns_dir); + goto out; + } + + result = 0; + +out: + return result; +} + +static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) +{ + unsigned int ns_id; + ssize_t result; + + result = -EINVAL; + + if (sscanf(data, "%u", &ns_id) != 1) { + pr_err("IMA: invalid namespace id: %s\n", data); + goto out; + } + + if (check_mntns(ns_id)) { + result = -ENOENT; + pr_err("IMA: unused namespace id %u\n", ns_id); + goto out; + } + + result = create_mnt_ns_directory(ns_id); + if (result != 0) { + pr_err("IMA: namespace id %u directory creation failed\n", ns_id); + goto out; + } + + result = datalen; + pr_info("IMA: directory created for namespace id %u\n", ns_id); + +out: + return result; +} + +static ssize_t ima_write_namespaces(struct file *file, const char __user *buf, + size_t datalen, loff_t *ppos) +{ + char *data; + ssize_t result; + + if (datalen >= PAGE_SIZE) + datalen = PAGE_SIZE - 1; + + /* No partial writes. */ + result = -EINVAL; + if (*ppos != 0) + goto out; + + result = -ENOMEM; + data = kmalloc(datalen + 1, GFP_KERNEL); + if (!data) + goto out; + + *(data + datalen) = '\0'; + + result = -EFAULT; + if (copy_from_user(data, buf, datalen)) + goto out_free; + + result = mutex_lock_interruptible(&ima_write_mutex); + if (result < 0) + goto out_free; + + result = handle_new_namespace_policy(data, datalen); + + mutex_unlock(&ima_write_mutex); + +out_free: + kfree(data); +out: + return result; +} + +static int ima_open_namespaces(struct inode *inode, struct file *filp) +{ + if (!(filp->f_flags & O_WRONLY)) + return -EACCES; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags)) + return -EBUSY; + return 0; +} + +static int ima_release_namespaces(struct inode *inode, struct file *file) +{ + clear_bit(IMA_FS_BUSY, &ima_fs_flags); + + return 0; +} + +static const struct file_operations ima_namespaces_ops = { + .open = ima_open_namespaces, + .write = ima_write_namespaces, + .read = seq_read, + .release = ima_release_namespaces, + .llseek = generic_file_llseek, +}; +#endif + int __init ima_fs_init(void) { ima_dir = securityfs_create_dir("ima", NULL); @@ -490,6 +662,14 @@ int __init ima_fs_init(void) if (IS_ERR(ima_policy)) goto out; +#ifdef CONFIG_IMA_PER_NAMESPACE + ima_namespaces = securityfs_create_file("namespaces", NAMESPACES_FILE_FLAGS, + ima_dir, NULL, + &ima_namespaces_ops); + if (IS_ERR(ima_namespaces)) + goto out; +#endif + return 0; out: securityfs_remove(violations); @@ -498,5 +678,8 @@ int __init ima_fs_init(void) securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_dir); securityfs_remove(ima_policy); +#ifdef CONFIG_IMA_PER_NAMESPACE + securityfs_remove(ima_namespaces); +#endif return -1; } -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:13
|
New ima_ns_policy structure to describe IMA policy data per namespace. Using a radix tree to map namespace ids to a respective ima_ns_policy structure. When it is needed to retrieve IMA policy rules/flags, the target ima_ns_policy structure is retrieved from the radix tree by getting the namespace id from the current context. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima.h | 37 +++++++++++++++++ security/integrity/ima/ima_fs.c | 79 ++++++++++++++++++++++++++++++++++--- security/integrity/ima/ima_init.c | 2 + security/integrity/ima/ima_policy.c | 29 +++++++++----- 4 files changed, 133 insertions(+), 14 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6e8ca8e..1c5c875 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -140,6 +140,21 @@ static inline void ima_load_kexec_buffer(void) {} */ extern bool ima_canonical_fmt; +/* Namespace policy globals */ +struct ima_ns_policy { + struct dentry *policy_dentry; + struct dentry *ns_dentry; + struct list_head *ima_rules; + struct list_head ima_policy_rules; + int ima_policy_flag; + int ima_appraise; +}; + +#ifdef CONFIG_IMA_PER_NAMESPACE +extern spinlock_t ima_ns_policy_lock; +extern struct radix_tree_root ima_ns_policy_mapping; +#endif + /* Internal IMA function definitions */ int ima_init(void); int ima_fs_init(void); @@ -166,6 +181,27 @@ int ima_measurements_show(struct seq_file *m, void *v); unsigned long ima_get_binary_runtime_size(void); int ima_init_template(void); void ima_init_template_list(void); +#ifdef CONFIG_IMA_PER_NAMESPACE +static inline void ima_namespace_lock_init(void) { + spin_lock_init(&ima_ns_policy_lock); +} +static inline void ima_namespace_lock(void) { + spin_lock(&ima_ns_policy_lock); +} +static inline void ima_namespace_unlock(void) { + spin_unlock(&ima_ns_policy_lock); +} +#else +static inline void ima_namespace_lock_init(void) { + return; +} +static inline void ima_namespace_lock(void) { + return; +} +static inline void ima_namespace_unlock(void) { + return; +} +#endif /* * used to protect h_table and sha_table @@ -226,6 +262,7 @@ void ima_update_policy(void); void ima_update_policy_flag(void); ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); +void ima_free_policy_rules(struct list_head *policy_rules); int ima_check_policy(void); void *ima_policy_start(struct seq_file *m, loff_t *pos); void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 6456407..ce6dcdf 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -275,6 +275,48 @@ static const struct file_operations ima_ascii_measurements_ops = { }; #ifdef CONFIG_IMA_PER_NAMESPACE +/* used for namespace policy rules initialization */ +static LIST_HEAD(empty_policy); + +static int allocate_namespace_policy(struct ima_ns_policy **ins, + struct dentry *policy_dentry, struct dentry *ns_dentry) +{ + int result; + struct ima_ns_policy *p; + + p = kmalloc(sizeof(struct ima_ns_policy), GFP_KERNEL); + if (!p) { + result = -ENOMEM; + goto out; + } + + p->policy_dentry = policy_dentry; + p->ns_dentry = ns_dentry; + p->ima_appraise = 0; + p->ima_policy_flag = 0; + INIT_LIST_HEAD(&p->ima_policy_rules); + /* namespace starts with empty rules and not pointing to + * ima_policy_rules */ + p->ima_rules = &empty_policy; + + result = 0; + *ins = p; + +out: + return result; +} + +static void free_namespace_policy(struct ima_ns_policy *ins) +{ + if (ins->policy_dentry) + securityfs_remove(ins->policy_dentry); + securityfs_remove(ins->ns_dentry); + + ima_free_policy_rules(&ins->ima_policy_rules); + + kfree(ins); +} + /* * check_mntns: check a mount namespace is valid * @@ -476,9 +518,11 @@ static int ima_release_policy(struct inode *inode, struct file *file) #ifndef CONFIG_IMA_WRITE_POLICY securityfs_remove(ima_policy); ima_policy = NULL; -#else - clear_bit(IMA_FS_BUSY, &ima_fs_flags); #endif + + /* always clear the busy flag so other namespaces can use it */ + clear_bit(IMA_FS_BUSY, &ima_fs_flags); + return 0; } @@ -500,11 +544,14 @@ static int create_mnt_ns_directory(unsigned int ns_id) int result; struct dentry *ns_dir, *ns_policy; char dir_name[64]; + struct ima_ns_policy *ins; snprintf(dir_name, sizeof(dir_name), "%u", ns_id); ns_dir = securityfs_create_dir(dir_name, ima_dir); if (IS_ERR(ns_dir)) { + /* TODO: handle EEXIST error, remove the folder and + continue the procedure */ result = PTR_ERR(ns_dir); goto out; } @@ -518,7 +565,15 @@ static int create_mnt_ns_directory(unsigned int ns_id) goto out; } - result = 0; + result = allocate_namespace_policy(&ins, ns_policy, ns_dir); + if (!result) { + result = radix_tree_insert(&ima_ns_policy_mapping, ns_id, ins); + if (result) + free_namespace_policy(ins); + } else { + securityfs_remove(ns_policy); + securityfs_remove(ns_dir); + } out: return result; @@ -528,6 +583,7 @@ static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) { unsigned int ns_id; ssize_t result; + struct ima_ns_policy *ins; result = -EINVAL; @@ -536,21 +592,34 @@ static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) goto out; } + rcu_read_lock(); + ins = radix_tree_lookup(&ima_ns_policy_mapping, ns_id); + rcu_read_unlock(); + if (ins) { + pr_info("IMA: directory for namespace id %u already created\n", ns_id); + result = datalen; + goto out; + } + + ima_namespace_lock(); if (check_mntns(ns_id)) { result = -ENOENT; pr_err("IMA: unused namespace id %u\n", ns_id); - goto out; + goto out_unlock; } result = create_mnt_ns_directory(ns_id); if (result != 0) { pr_err("IMA: namespace id %u directory creation failed\n", ns_id); - goto out; + goto out_unlock; } result = datalen; pr_info("IMA: directory created for namespace id %u\n", ns_id); +out_unlock: + ima_namespace_unlock(); + out: return result; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 2967d49..b557ee3 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -135,6 +135,8 @@ int __init ima_init(void) if (rc != 0) return rc; + ima_namespace_lock_init(); + ima_init_policy(); return ima_fs_init(); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index aed47b7..2e8c3b7 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -47,6 +47,12 @@ int ima_policy_flag; static int temp_ima_appraise; +#ifdef CONFIG_IMA_PER_NAMESPACE +/* policy namespace map entries except the initial namespace policy */ +RADIX_TREE(ima_ns_policy_mapping, GFP_ATOMIC); +spinlock_t ima_ns_policy_lock; +#endif + #define MAX_LSM_RULES 6 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE @@ -863,19 +869,12 @@ ssize_t ima_parse_add_rule(char *rule) return len; } -/** - * ima_delete_rules() called to cleanup invalid in-flight policy. - * We don't need locking as we operate on the temp list, which is - * different from the active one. There is also only one user of - * ima_delete_rules() at a time. - */ -void ima_delete_rules(void) +void ima_free_policy_rules(struct list_head *policy_rules) { struct ima_rule_entry *entry, *tmp; int i; - temp_ima_appraise = 0; - list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { + list_for_each_entry_safe(entry, tmp, policy_rules, list) { for (i = 0; i < MAX_LSM_RULES; i++) kfree(entry->lsm[i].args_p); @@ -884,6 +883,18 @@ void ima_delete_rules(void) } } +/** + * ima_delete_rules() called to cleanup invalid in-flight policy. + * We don't need locking as we operate on the temp list, which is + * different from the active one. There is also only one user of + * ima_delete_rules() at a time. + */ +void ima_delete_rules(void) +{ + temp_ima_appraise = 0; + ima_free_policy_rules(&ima_temp_rules); +} + #ifdef CONFIG_IMA_READ_POLICY enum { mask_exec = 0, mask_write, mask_read, mask_append -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:10
|
Release all namespace IMA policy resources when the mount namespace is released. This is the suggested mechanism to release namespace policy resources, but we still can discuss other methods to avoid cross-component changes. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- fs/namespace.c | 4 ++++ include/linux/integrity.h | 9 +++++++++ security/integrity/ima/ima_fs.c | 26 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index cc1375ef..80940998 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -15,6 +15,7 @@ #include <linux/user_namespace.h> #include <linux/namei.h> #include <linux/security.h> +#include <linux/integrity.h> #include <linux/cred.h> #include <linux/idr.h> #include <linux/init.h> /* init_rootfs */ @@ -3283,6 +3284,9 @@ void put_mnt_ns(struct mnt_namespace *ns) { if (!atomic_dec_and_test(&ns->count)) return; + + ima_mnt_namespace_dying(ns->ns.inum); + drop_collected_mounts(&ns->root->mnt); free_mnt_ns(ns); } diff --git a/include/linux/integrity.h b/include/linux/integrity.h index c2d6082..034d082 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -43,4 +43,13 @@ static inline void integrity_load_keys(void) } #endif /* CONFIG_INTEGRITY */ +#ifdef CONFIG_IMA_PER_NAMESPACE +extern void ima_mnt_namespace_dying(unsigned int ns_id); +#else +static inline void ima_mnt_namespace_dying(unsigned int ns_id) +{ + return; +} +#endif /* CONFIG_IMA_PER_NAMESPACE */ + #endif /* _LINUX_INTEGRITY_H */ diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ce6dcdf..56ba0ff 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -423,6 +423,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, "policy_update", "signed policy required", 1, 0); + if (ima_appraise & IMA_APPRAISE_ENFORCE) result = -EACCES; } else { @@ -579,6 +580,31 @@ static int create_mnt_ns_directory(unsigned int ns_id) return result; } +/* + * ima_mnt_namespace_dying - releases all namespace policy resources + * It is called automatically when the namespace is released. + * @ns_id namespace id to be released + * + * Note: This function is called by put_mnt_ns() in the context + * of a namespace release. We need to make sure that a lock on + * this path is allowed. + */ +void ima_mnt_namespace_dying(unsigned int ns_id) +{ + struct ima_ns_policy *p; + + spin_lock(&ima_ns_policy_lock); + p = radix_tree_delete(&ima_ns_policy_mapping, ns_id); + + if (!p) { + spin_unlock(&ima_ns_policy_lock); + return; + } + + free_namespace_policy(p); + spin_unlock(&ima_ns_policy_lock); +} + static ssize_t handle_new_namespace_policy(const char *data, size_t datalen) { unsigned int ns_id; -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:01:04
|
Adding new fields (mount namespace id, file inode and device name) to uniquely identify a pathname in the measurement file considering multiple mount namespaces. The file inode on a given device is unique and these fields are required to identify a namespace id since this id can be released and later reused by a different namespace. These new fields are added to all measurement templates if CONFIG_IMA_PER_NAMESPACE is defined. There will still be one single measurement file even with multiple namespaces, since for the remote attestion a single and complete list is required. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/Kconfig | 8 ++++ security/integrity/ima/ima.h | 12 ++++++ security/integrity/ima/ima_template.c | 10 ++++- security/integrity/ima/ima_template_lib.c | 70 +++++++++++++++++++++++++++++++ security/integrity/ima/ima_template_lib.h | 13 ++++++ 5 files changed, 111 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 370eb2f..7331ff6 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -219,3 +219,11 @@ config IMA_APPRAISE_SIGNED_INIT default n help This option requires user-space init to be signed. + +config IMA_PER_NAMESPACE + bool "Enable per mount-namespace handling of IMA policy." + depends on IMA + default n + help + This option enables another API in securityfs allowing IMA policies to + be defined per mount namespace. diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b563fbd..42fb91ba 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -47,7 +47,19 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 #define IMA_TEMPLATE_IMA_NAME "ima" +#define IMA_TEMPLATE_IMA_NG_NAME "ima-ng" +#define IMA_TEMPLATE_IMA_SIG_NAME "ima-sig" + +#ifndef CONFIG_IMA_PER_NAMESPACE #define IMA_TEMPLATE_IMA_FMT "d|n" +#define IMA_TEMPLATE_IMA_NG_FMT "d-ng|n-ng" +#define IMA_TEMPLATE_IMA_SIG_FMT "d-ng|n-ng|sig" +#else +#define IMA_TEMPLATE_IMA_FMT "nid|fi|dev|d|n" +#define IMA_TEMPLATE_IMA_NG_FMT "nid|fi|dev|d-ng|n-ng" +#define IMA_TEMPLATE_IMA_SIG_FMT "nid|fi|dev|d-ng|n-ng|sig" +#endif + /* current content of the policy */ extern int ima_policy_flag; diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index cebb37c..db65c09 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -21,8 +21,8 @@ static struct ima_template_desc builtin_templates[] = { {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, - {.name = "ima-ng", .fmt = "d-ng|n-ng"}, - {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, + {.name = IMA_TEMPLATE_IMA_NG_NAME, .fmt = IMA_TEMPLATE_IMA_NG_FMT}, + {.name = IMA_TEMPLATE_IMA_SIG_NAME, .fmt = IMA_TEMPLATE_IMA_SIG_FMT}, {.name = "", .fmt = ""}, /* placeholder for a custom format */ }; @@ -40,6 +40,12 @@ static struct ima_template_field supported_fields[] = { .field_show = ima_show_template_string}, {.field_id = "sig", .field_init = ima_eventsig_init, .field_show = ima_show_template_sig}, + {.field_id = "nid", .field_init = ima_namespaceid_init, + .field_show = ima_show_namespaceid}, + {.field_id = "fi", .field_init = ima_filei_init, + .field_show = ima_show_filei}, + {.field_id = "dev", .field_init = ima_dev_init, + .field_show = ima_show_dev}, }; #define MAX_TEMPLATE_NAME_LEN 15 diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index f9ba37b..50cde10 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -14,6 +14,8 @@ */ #include "ima_template_lib.h" +#include <linux/proc_ns.h> +#include <linux/types.h> static bool ima_template_hash_algo_allowed(u8 algo) { @@ -330,3 +332,71 @@ int ima_eventsig_init(struct ima_event_data *event_data, out: return rc; } + +int ima_namespaceid_init(struct ima_event_data *event_data, + struct ima_field_data *field_data) +{ + u8 tmpbuf[64]; + struct ns_common *ns; + + ns = mntns_operations.get(current); + snprintf(tmpbuf, sizeof(tmpbuf), "mnt-ns=%u", ns->inum); + mntns_operations.put(ns); + + return ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data); +} + +void ima_show_namespaceid(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data) +{ + ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); +} + +int ima_filei_init(struct ima_event_data *event_data, + struct ima_field_data *field_data) +{ + u8 tmpbuf[64]; + struct inode *inode; + int rc = 0; + + if (event_data->file) { + inode = file_inode(event_data->file); + snprintf(tmpbuf, sizeof(tmpbuf), "inode=%lu", inode->i_ino); + rc = ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data); + } else { + pr_info("IMA: event file is NULL\n"); + } + + return rc; +} + +void ima_show_filei(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data) +{ + ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); +} + +int ima_dev_init(struct ima_event_data *event_data, + struct ima_field_data *field_data) +{ + u8 tmpbuf[64]; + struct inode *inode; + int rc = 0; + + if (event_data->file) { + inode = file_inode(event_data->file); + snprintf(tmpbuf, sizeof(tmpbuf), "dev=%s", inode->i_sb->s_id); //TODO: check untrusted string? see audit_log_n_untrustedstring() + tmpbuf[sizeof(tmpbuf) - 1] = 0; + rc = ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data); + } else { + pr_info("IMA: event file is NULL\n"); + } + + return rc; +} + +void ima_show_dev(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data) +{ + ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); +} diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h index c344530..cf6a6c7 100644 --- a/security/integrity/ima/ima_template_lib.h +++ b/security/integrity/ima/ima_template_lib.h @@ -26,6 +26,12 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show, struct ima_field_data *field_data); void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, struct ima_field_data *field_data); +void ima_show_namespaceid(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data); +void ima_show_filei(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data); +void ima_show_dev(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data); int ima_eventdigest_init(struct ima_event_data *event_data, struct ima_field_data *field_data); int ima_eventname_init(struct ima_event_data *event_data, @@ -36,4 +42,11 @@ int ima_eventname_ng_init(struct ima_event_data *event_data, struct ima_field_data *field_data); int ima_eventsig_init(struct ima_event_data *event_data, struct ima_field_data *field_data); +int ima_namespaceid_init(struct ima_event_data *event_data, + struct ima_field_data *field_data); +int ima_filei_init(struct ima_event_data *event_data, + struct ima_field_data *field_data); +int ima_dev_init(struct ima_event_data *event_data, + struct ima_field_data *field_data); + #endif /* __LINUX_IMA_TEMPLATE_LIB_H */ -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:00:59
|
Adding new field (mount namespace id, along with already existent file inode and device name) to uniquely identify a pathname considering different mount namespaces. The file inode on a given device is unique and these fields are required to identify a namespace id since this id can be released and later reused by a different namespace. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/integrity_audit.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c index 90987d1..e675e42 100644 --- a/security/integrity/integrity_audit.c +++ b/security/integrity/integrity_audit.c @@ -13,6 +13,7 @@ #include <linux/fs.h> #include <linux/gfp.h> #include <linux/audit.h> +#include <linux/proc_ns.h> #include "integrity.h" static int integrity_audit_info; @@ -52,8 +53,12 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, get_task_comm(name, current)); if (fname) { + struct ns_common *ns; audit_log_format(ab, " name="); audit_log_untrustedstring(ab, fname); + ns = mntns_operations.get(current); + audit_log_format(ab, " mnt_ns=%u", ns->inum); + mntns_operations.put(ns); } if (inode) { audit_log_format(ab, " dev="); -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:00:58
|
Adding new fields (mount namespace id, file inode and device name) to uniquely identify a pathname considering different mount namespaces. The file inode on a given device is unique and these fields are required to identify a namespace id since this id can be released and later reused by a different namespace. Signed-off-by: Guilherme Magalhaes <gui...@hp...> --- security/integrity/ima/ima_api.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index c2edba8..b05c1fd 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -18,6 +18,7 @@ #include <linux/fs.h> #include <linux/xattr.h> #include <linux/evm.h> +#include <linux/proc_ns.h> #include "ima.h" @@ -293,6 +294,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, char hash[(iint->ima_hash->length * 2) + 1]; const char *algo_name = hash_algo_name[iint->ima_hash->algo]; char algo_hash[sizeof(hash) + strlen(algo_name) + 2]; + struct ns_common *ns; int i; if (iint->flags & IMA_AUDITED) @@ -312,6 +314,12 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, audit_log_format(ab, " hash="); snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash); audit_log_untrustedstring(ab, algo_hash); + ns = mntns_operations.get(current); + audit_log_format(ab, " mnt_ns=%u", ns->inum); + mntns_operations.put(ns); + audit_log_format(ab, " dev="); + audit_log_untrustedstring(ab, iint->inode->i_sb->s_id); + audit_log_format(ab, " ino=%lu", iint->inode->i_ino); audit_log_task_info(ab, current); audit_log_end(ab); -- 2.7.4 |
From: Guilherme M. <gui...@hp...> - 2017-05-11 14:00:50
|
The IMA policy rules and policy/appraise flags are now encapsulated on a new structure which completely describes the policy for a given namespace. The correct namespace structure is retrieved from a radix tree based on the namespace id in use by the process in the context whenever the IMA policy rules or flags are needed. The existent securityfs interface is reused to define policy per namespace. A new namespace file is used to create a folder for a given namespace id with a policy file which can then be used to define rules for that namespace. Patches 1, 2 and 4 qualify the file pathname considering multiple namespaces. Patch 3 adds a new kernel config which enables all the policy per namespace functionality. Patch 5 adds the namespace securityfs file which is the interface to define IMA policy per namespace. New policy file is creanted for each namespace and the policy securityfs mechanism is completely reused. Patche 7 adds a hook to fs/namespace.c to automatically delete all namespace IMA policy resources such as radix tree entry and securityfs files. Patches 8, 10, 11 and 14 are small implementation details Patches 6, 9, 12 are key changes to encapsulate all policy rules and flags in a structure per namespace. The correct structure is retrieved for the target namespace and the namespace rules are used on that context. Patch 13 adds the enforce_ns appraise mode which enables different appraise modes per namespace. Other areas might still need work to completely namespace IMA. For instance, EVM and templates per namespace are not yet covered. Guilherme Magalhaes (11): ima: qualify pathname in audit info record ima: qualify pathname in audit measurement record ima: qualify pathname in measurement file ima: add support to namespace securityfs file ima: store new namespace policy structure in a radix tree ima, fs: release namespace policy resources ima: new namespace policy structure to track initial namespace policy data ima: block initial namespace id on the namespace policy interface ima: delete namespace policy securityfs file in write-once mode ima: handling all policy flags per namespace using ima_ns_policy structure ima: appraise mode per namespace with new enforce_ns appraise mode fs/namespace.c | 4 + include/linux/integrity.h | 9 + security/integrity/ima/Kconfig | 8 + security/integrity/ima/ima.h | 78 ++++- security/integrity/ima/ima_api.c | 14 +- security/integrity/ima/ima_appraise.c | 30 +- security/integrity/ima/ima_fs.c | 454 ++++++++++++++++++++++++++++-- security/integrity/ima/ima_init.c | 13 +- security/integrity/ima/ima_main.c | 40 ++- security/integrity/ima/ima_policy.c | 210 +++++++++++--- security/integrity/ima/ima_template.c | 10 +- security/integrity/ima/ima_template_lib.c | 70 +++++ security/integrity/ima/ima_template_lib.h | 13 + security/integrity/integrity_audit.c | 5 + 14 files changed, 860 insertions(+), 98 deletions(-) -- 2.7.4 |
From: Pavel S. <psh...@sa...> - 2017-05-08 20:56:13
|
2017-05-06 5:59 GMT-07:00 Gilad Ben-Yossef <gi...@be...>: > cifs starts an async. crypto op and waits for their completion. > Move it over to generic code doing the same. > > Signed-off-by: Gilad Ben-Yossef <gi...@be...> > --- > fs/cifs/smb2ops.c | 30 ++++-------------------------- > 1 file changed, 4 insertions(+), 26 deletions(-) > > diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c > index 152e37f..cee7bb3 100644 > --- a/fs/cifs/smb2ops.c > +++ b/fs/cifs/smb2ops.c > @@ -1706,22 +1706,6 @@ init_sg(struct smb_rqst *rqst, u8 *sign) > return sg; > } > > -struct cifs_crypt_result { > - int err; > - struct completion completion; > -}; > - > -static void cifs_crypt_complete(struct crypto_async_request *req, int err) > -{ > - struct cifs_crypt_result *res = req->data; > - > - if (err == -EINPROGRESS) > - return; > - > - res->err = err; > - complete(&res->completion); > -} > - > static int > smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) > { > @@ -1762,12 +1746,10 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) > struct aead_request *req; > char *iv; > unsigned int iv_len; > - struct cifs_crypt_result result = {0, }; > + DECLARE_CRYPTO_WAIT(wait); > struct crypto_aead *tfm; > unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); > > - init_completion(&result.completion); > - > rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key); > if (rc) { > cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__, > @@ -1825,14 +1807,10 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc) > aead_request_set_ad(req, assoc_data_len); > > aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, > - cifs_crypt_complete, &result); > + crypto_req_done, &wait); > > - rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); > - > - if (rc == -EINPROGRESS || rc == -EBUSY) { > - wait_for_completion(&result.completion); > - rc = result.err; > - } > + rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) > + : crypto_aead_decrypt(req), &wait); > > if (!rc && enc) > memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); > -- > 2.1.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-cifs" in > the body of a message to maj...@vg... > More majordomo info at http://vger.kernel.org/majordomo-info.html Acked-by: Pavel Shilovsky <ps...@mi...> Best regards, Pavel Shilovsky |
From: Mimi Z. <zo...@li...> - 2017-05-08 15:45:39
|
On Sat, 2017-05-06 at 23:40 +0800, Geliang Tang wrote: > Use memdup_user_nul() helper instead of open-coding to simplify the > code. > > Signed-off-by: Geliang Tang <gel...@gm...> Thanks, this patch will be queued. Mimi > --- > security/integrity/ima/ima_fs.c | 13 ++++--------- > 1 file changed, 4 insertions(+), 9 deletions(-) > > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c > index ca303e5..ad491c5 100644 > --- a/security/integrity/ima/ima_fs.c > +++ b/security/integrity/ima/ima_fs.c > @@ -323,16 +323,11 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, > if (*ppos != 0) > goto out; > > - result = -ENOMEM; > - data = kmalloc(datalen + 1, GFP_KERNEL); > - if (!data) > + data = memdup_user_nul(buf, datalen); > + if (IS_ERR(data)) { > + result = PTR_ERR(data); > goto out; > - > - *(data + datalen) = '\0'; > - > - result = -EFAULT; > - if (copy_from_user(data, buf, datalen)) > - goto out_free; > + } > > result = mutex_lock_interruptible(&ima_write_mutex); > if (result < 0) |
From: Mimi Z. <zo...@li...> - 2017-05-08 14:27:44
|
Hi Markus, On Sun, 2017-05-07 at 15:40 +0200, SF Markus Elfring wrote: > From: Markus Elfring <el...@us...> > Date: Sun, 7 May 2017 15:35:15 +0200 > > A few update suggestions were taken into account > from static source code analysis. Sorry, these changes make backporting and upstreaming other changes more difficult without much benefit. Mimi |
From: Geliang T. <gel...@gm...> - 2017-05-06 15:40:42
|
Use memdup_user_nul() helper instead of open-coding to simplify the code. Signed-off-by: Geliang Tang <gel...@gm...> --- security/integrity/ima/ima_fs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ca303e5..ad491c5 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -323,16 +323,11 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (*ppos != 0) goto out; - result = -ENOMEM; - data = kmalloc(datalen + 1, GFP_KERNEL); - if (!data) + data = memdup_user_nul(buf, datalen); + if (IS_ERR(data)) { + result = PTR_ERR(data); goto out; - - *(data + datalen) = '\0'; - - result = -EFAULT; - if (copy_from_user(data, buf, datalen)) - goto out_free; + } result = mutex_lock_interruptible(&ima_write_mutex); if (result < 0) -- 2.9.3 |
From: Fengguang Wu <fen...@in...> - 2017-04-11 09:23:12
|
Greetings, 0day kernel testing robot got the below dmesg and the first bad commit is https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master commit 05d1a717ec0430c916a749b94eb90ab74bbfa356 Author: Mimi Zohar <zo...@li...> AuthorDate: Mon Feb 29 19:52:05 2016 -0500 Commit: Mimi Zohar <zo...@li...> CommitDate: Sun May 1 09:23:52 2016 -0400 ima: add support for creating files using the mknodat syscall Commit 3034a14 "ima: pass 'opened' flag to identify newly created files" stopped identifying empty files as new files. However new empty files can be created using the mknodat syscall. On systems with IMA-appraisal enabled, these empty files are not labeled with security.ima extended attributes properly, preventing them from subsequently being opened in order to write the file data contents. This patch defines a new hook named ima_post_path_mknod() to mark these empty files, created using mknodat, as new in order to allow the file data contents to be written. In addition, files with security.ima xattrs containing a file signature are considered "immutable" and can not be modified. The file contents need to be written, before signing the file. This patch relaxes this requirement for new files, allowing the file signature to be written before the file contents. Changelog: - defer identifying files with signatures stored as security.ima (based on Dmitry Rozhkov's comments) - removing tests (eg. dentry, dentry->d_inode, inode->i_size == 0) (based on Al's review) Signed-off-by: Mimi Zohar <zo...@li...> Cc: Al Viro <<vi...@ze...> Tested-by: Dmitry Rozhkov <dmi...@li...> 42a4c60319 ima: fix ima_inode_post_setattr 05d1a717ec ima: add support for creating files using the mknodat syscall 39da7c509a Linux 4.11-rc6 +--------------------------------------------------------------------------+------------+------------+-----------+ | | 42a4c60319 | 05d1a717ec | v4.11-rc6 | +--------------------------------------------------------------------------+------------+------------+-----------+ | boot_successes | 1009 | 889 | 908 | | boot_failures | 28 | 20 | 4 | | BUG:unable_to_handle_kernel | 28 | 20 | 4 | | Oops:#[##] | 28 | 20 | 4 | | EIP_is_at_perf_prepare_sample | 28 | 16 | | | Kernel_panic-not_syncing:Fatal_exception | 18 | 14 | 4 | | Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 10 | 6 | | | calltrace:SyS_fstatat64 | 3 | 1 | | | BUG:sleeping_function_called_from_invalid_context_at_arch/x86/mm/fault.c | 0 | 4 | 4 | | calltrace:SyS_mknodat | 0 | 4 | | | calltrace:SyS_mknod | 0 | 4 | | | EIP_is_at_ima_match_policy | 0 | 4 | | | EIP:ima_match_policy | 0 | 0 | 4 | +--------------------------------------------------------------------------+------------+------------+-----------+ [ 18.784299] caif:caif_disconnect_client(): nothing to disconnect [ 18.792568] caif:caif_disconnect_client(): nothing to disconnect [ 18.801310] caif:caif_disconnect_client(): nothing to disconnect [ 18.809277] caif:caif_disconnect_client(): nothing to disconnect [ 18.817304] caif:caif_disconnect_client(): nothing to disconnect [ 19.258978] BUG: sleeping function called from invalid context at arch/x86/mm/fault.c:1304 [ 19.267526] in_atomic(): 0, irqs_disabled(): 0, pid: 1612, name: trinity-c0 [ 19.273303] 4 locks held by trinity-c0/1612: [ 19.279773] #0: (sb_writers#4){......}, at: [<c1125588>] __sb_start_write+0x57/0x9a [ 19.293773] #1: (&sb->s_type->i_mutex_key#9/1){......}, at: [<c112ea9e>] filename_create+0x5d/0xf3 [ 19.303991] #2: (rcu_read_lock){......}, at: [<c136ec06>] ima_match_policy+0x0/0x2c1 [ 19.312833] #3: (&mm->mmap_sem){......}, at: [<c105940d>] __do_page_fault+0x154/0x3d5 [ 19.321244] CPU: 0 PID: 1612 Comm: trinity-c0 Not tainted 4.6.0-rc2-00011-g05d1a71 #1 [ 19.331050] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014 [ 19.339031] 00000000 d08c3480 ccc65e08 c13aeae7 ccc65e1c c107ac7c d08c3480 00000000 [ 19.345350] 00000000 ccc65e38 c107acee 00000001 00000001 00000000 00000000 ccc65e98 [ 19.352387] ccc65e74 c105945f 00000000 00000000 00000000 00000000 cff59660 c107df62 [ 19.356460] Call Trace: [ 19.360396] [<c13aeae7>] dump_stack+0x16/0x18 [ 19.362145] [<c107ac7c>] ___might_sleep+0x11e/0x126 [ 19.364037] [<c107acee>] __might_sleep+0x6a/0x71 [ 19.365789] [<c105945f>] __do_page_fault+0x1a6/0x3d5 [ 19.370161] [<c107df62>] ? local_clock+0x19/0x1c [ 19.371814] [<c10572d5>] ? kvm_sched_clock_read+0x9/0x18 [ 19.373868] [<c1057135>] ? kvm_async_pf_task_wake+0xeb/0xeb [ 19.375775] [<c1059938>] do_page_fault+0x25/0x29 [ 19.377450] [<c1057157>] do_async_page_fault+0x22/0x5e [ 19.381714] [<c1839be5>] error_code+0x65/0x70 [ 19.383453] [<c136ec50>] ? ima_match_policy+0x4a/0x2c1 [ 19.385285] [<c13b8ef3>] ? lockref_get+0x15/0x18 [ 19.414917] [<c136f53e>] ima_must_appraise+0x1b/0x25 [ 19.416806] [<c136d39b>] ima_post_path_mknod+0x18/0x31 [ 19.421343] [<c112f1b8>] SyS_mknodat+0x131/0x187 [ 19.423173] [<c112f223>] SyS_mknod+0x15/0x17 [ 19.424820] [<c1000fbc>] do_int80_syscall_32+0x53/0x9a [ 19.426668] [<c1839101>] entry_INT80_32+0x31/0x31 [ 19.430923] BUG: unable to handle kernel NULL pointer dereference at (null) [ 19.433551] IP: [<c136ec50>] ima_match_policy+0x4a/0x2c1 [ 19.435553] *pdpt = 000000000cc60001 *pde = 0000000000000000 [ 19.441485] Oops: 0000 [#1] PREEMPT DEBUG_PAGEALLOC [ 19.443671] Modules linked in: [ 19.445237] CPU: 0 PID: 1612 Comm: trinity-c0 Not tainted 4.6.0-rc2-00011-g05d1a71 #1 [ 19.451278] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014 [ 19.454767] task: d08c3480 ti: ccc64000 task.ti: ccc64000 [ 19.456645] EIP: 0060:[<c136ec50>] EFLAGS: 00010286 CPU: 0 [ 19.461079] EIP is at ima_match_policy+0x4a/0x2c1 [ 19.462773] EAX: 00000000 EBX: 00000001 ECX: 15c2f201 EDX: 00000000 [ 19.464763] ESI: 00000000 EDI: 00000000 EBP: ccc65f14 ESP: ccc65ed4 [ 19.466784] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 [ 19.471266] CR0: 80050033 CR2: 00000000 CR3: 0cc218e0 CR4: 000406f0 [ 19.473620] DR0: 09a7c000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 19.475758] DR6: ffff0ff0 DR7: 00030602 [ 19.477254] Stack: [ 19.481017] c13b8ef3 cf696070 ccc65f00 00000010 00008d45 58eba135 cfe0f030 0000000c [ 19.484752] 00000000 00000001 c1852140 cd1a1000 ccc65f2c 00000001 00000000 00000000 [ 19.491467] ccc65f24 c136f53e 00000004 cfe0f030 ccc65f30 c136d39b cd1a1000 ccc65f64 [ 19.495212] Call Trace: [ 19.496416] [<c13b8ef3>] ? lockref_get+0x15/0x18 [ 19.500533] [<c136f53e>] ima_must_appraise+0x1b/0x25 [ 19.502271] [<c136d39b>] ima_post_path_mknod+0x18/0x31 [ 19.504001] [<c112f1b8>] SyS_mknodat+0x131/0x187 [ 19.505599] [<c112f223>] SyS_mknod+0x15/0x17 [ 19.507139] [<c1000fbc>] do_int80_syscall_32+0x53/0x9a [ 19.510850] [<c1839101>] entry_INT80_32+0x31/0x31 [ 19.517472] Code: 99 d2 ff b8 68 1c d7 c1 31 c9 31 d2 68 06 ec 36 c1 6a 00 6a 00 6a 02 e8 e8 7a d1 ff a1 b0 42 48 c2 83 c4 10 c7 45 e0 00 00 00 00 <8b> 18 a1 70 93 c2 c1 89 45 d0 89 45 c0 3b 1d b0 42 48 c2 0f 84 [ 19.541611] EIP: [<c136ec50>] ima_match_policy+0x4a/0x2c1 SS:ESP 0068:ccc65ed4 [ 19.549818] CR2: 0000000000000000 [ 19.551239] ---[ end trace 16992df93ec11794 ]--- [ 19.570613] Kernel panic - not syncing: Fatal exception # HH:MM RESULT GOOD BAD GOOD_BUT_DIRTY DIRTY_NOT_BAD git bisect start v4.7 v4.6 -- git bisect bad 4340fa55298d17049e71c7a34e04647379c269f3 # 03:27 B 44 1 0 0 Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm git bisect bad 0eff4589c36edd03d50b835d0768b2c2ef3f20bd # 04:18 B 387 1 0 0 Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux git bisect good 8908c94d6cd7513ba4512295abc945a6ff7f979c # 16:16 G 908 0 0 0 Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6 git bisect bad 7beaa24ba49717419e24d1f6321e8b3c265a719c # 16:36 B 17 1 0 0 Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm git bisect good 9797f6b0504122e4ad9ff047a3d0521ad6706386 # 06:09 G 902 0 0 0 Merge tag 'armsoc-defconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc git bisect good 676d9735cd010fc439566e2b6e9b6adc3e1179ef # 18:15 G 900 0 1 1 Merge tag 'rpmsg-v4.7' of git://github.com/andersson/remoteproc git bisect good 2600a46ee0ed57c0e0a382c2a37ebac64d374d20 # 07:21 G 909 0 0 0 Merge tag 'trace-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace git bisect bad 0efacbbaee1e94e9942da0912f5b46ffd45a74bd # 07:32 B 5 2 0 0 Merge tag 'arc-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc git bisect bad f4f27d0028aabce57e44c16c2fdefccd6310d2f3 # 07:41 B 0 1 12 0 Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security git bisect good d55201ce08bfae40ae0062be126f49471a55bcad # 20:15 G 900 0 25 25 Merge branch 'keys-trust' into keys-next git bisect bad 0250abcd726b4eba8a6175f09656fe544ed6491a # 20:47 B 455 1 9 9 Merge tag 'keys-next-20160505' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next git bisect good 9b091556a073a9f5f93e2ad23d118f45c4796a84 # 09:15 G 900 0 24 24 LSM: LoadPin for kernel file loading restrictions git bisect good 42a4c603198f0d45b7aa936d3ac6ba1b8bd14a1b # 22:12 G 908 0 27 27 ima: fix ima_inode_post_setattr git bisect bad 470bf1f27a1472264d18c84b324389509f0e30b3 # 22:34 B 0 1 12 0 seccomp: Fix comment typo git bisect bad 05d1a717ec0430c916a749b94eb90ab74bbfa356 # 23:04 B 146 1 4 4 ima: add support for creating files using the mknodat syscall # first bad commit: [05d1a717ec0430c916a749b94eb90ab74bbfa356] ima: add support for creating files using the mknodat syscall git bisect good 42a4c603198f0d45b7aa936d3ac6ba1b8bd14a1b # 23:28 G 1000 0 1 28 ima: fix ima_inode_post_setattr # extra tests with CONFIG_DEBUG_INFO_REDUCED git bisect bad 05d1a717ec0430c916a749b94eb90ab74bbfa356 # 23:59 B 75 1 3 3 ima: add support for creating files using the mknodat syscall # extra tests on HEAD of linux-devel/devel-catchup-201704042237 git bisect bad 43f7aefa53909294720237cd098ae65e0621218d # 23:59 B 33 2 0 0 0day head guard for 'devel-catchup-201704042237' # extra tests on tree/branch linus/master git bisect bad 39da7c509acff13fc8cb12ec1bb20337c988ed36 # 01:45 B 345 1 0 0 Linux 4.11-rc6 # extra tests with first bad commit reverted git bisect good 54ebf3717ff597d61e5f992ee2f5c8b9e8cf04ac # 16:11 G 908 0 0 0 Revert "ima: add support for creating files using the mknodat syscall" # extra tests on tree/branch linux-next/master --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/lkp Intel Corporation |
From: Ken G. <kg...@li...> - 2017-03-15 21:26:37
|
On 3/15/2017 10:01 AM, Micka wrote: > Do you know where I can find documentation about others PCRs ? which > project/binary use those PCRs ? In general, pre-OS code uses PCR 0-7. PCR 8-15 are post-OS. The DRTM stuff is at 17-22. Bitlocker uses 0-5, 8-11. I don't know of anything else in the Linux space other than PCR 10 for IMA. Avoid 15 and 23, which are resettable, unless you understand the implications. |
From: Mark D. B. <md...@ju...> - 2017-03-15 18:41:44
|
Micka <mic...@gm...> writes: > Do you know where I can find documentation about others PCRs ? which > project/binary use those PCRs ? A Trusted Computing Group Conformant TPM1.x TPM must provide a minimum of 24 PCR registers. They are numbered PCR0 through PCR23. PCRs 0-15 are Static while 16-23 are resettable via pcrReset semantics. Generally, unless you really understand what you are doing, only use PCRs 8-15 outside of the BIOS. See linux/Documentation/ABI/stable/sysfs-class-tpm In a Mesured Boot system, the PCR usage is typically going to be laid out something like this: PCR 0- 7 Measured by BIOS Sometimes (depends on your Measured Boot enabled BIOS): 0 BIOS 1 BIOS configuration 2 Option ROMs 3 Option ROM configuration 4 Master Boot Record 5 Master Boot Record configuration 6 State transition an wake events 7 Platform manufacturer specific measurements PCR 8-15 Measured by the Operating system Sometimes (depending on use of GRUB2 or ONIE boot loader) 8 First sector of TrustedGRUB2 kernel (diskboot.img) 9 TrustedGRUB2 kernel (core.img) 10 IMA 11 Various commandline arguments 13 Other modules loaded from disk 14 Suggested as the base for virtual TPMs 15 Typically left for 3rd Party Application Measurements PCR 16 Debug (Resettable) PCR 23 Application Support (Resettable) See also https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientTPMInterfaceSpecification_TIS__1-3_27_03212013.pdf https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2-0-v43-150126.pdf https://lwn.net/Articles/699551/ http://trousers.sourceforge.net/grub.html https://github.com/Rohde-Schwarz-Cybersecurity/TrustedGRUB2 > Also why I can't edit this file : "/sys/kernel/security/ima/policy" ? That is the running configuration. You may be able to add to it (IMA_WRITE_POLICY) or read it (IMA_READ_POLICY), but you may not edit it. > I'm using the root user, but I can't access it. How can I change the > policy of the ima ? Please read Documentation/ABI/testing/ima_policy Read integrity/ima/Kconfig Look at IMA_WRITE_POLICY, IMA_READ_POLICY, Configure CONFIG_IMA_READ_POLICY if you want users to be able to read the current policy that has been installed. Configure IMA_WRITE_POLICY if you want users to be able to extend the current policy that has been installed. You may set IMA_MEASURE_PCR_IDX between the ranges of 8 through 14 with the default being 10. Your initrd or initramfs is the place to load the ima/policy file you want to use. -- Mark |
From: sksehwjray <sks...@da...> - 2017-03-15 14:34:02
|
<html> <head> <style> p{margin-top:0;margin-bottom:0} </style> </head> <body> <table class="txc-wrapper" border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td class="txc-wrapper-td"><div class="txc-content-wrapper" style="color:#111;font-family:Apple SD Gothic Neo,Malgun Gothic,'맑은 고딕',sans-serif;font-size:10pt;line-height:1.5;"><div dir="ltr"><span id="gt-res-error" style="display: none;"></span><span id="result_box" lang="en"><span title="안녕하세요 ">Good morning</span></span></div><div dir="ltr"><span lang="en"><span title="안녕하세요 "><br></span><span title="저는 라즈베리파이2에서 ima/evm을 사용하고자 합니다 ">I want to use ima / evm in raspberry pi 2</span></span></div><div dir="ltr"><span lang="en"><span title="저는 라즈베리파이2에서 ima/evm을 사용하고자 합니다 "><br></span><span title="kernel compile을 통해 ime/evm을 활성화 하였습니다 ">Ime / evm enabled via kernel compile</span></span></div><div dir="ltr"><span lang="en"><span title="kernel compile을 통해 ime/evm을 활성화 하였습니다 "><br></span><span title="이후 라즈베리파이를 실행하여 /boot/cmdline.txt 파일에 ima_appraise=fix evm=fix를 적용하여 ima/evm을 생성하였습니다 ">I then created ima / evm by running raspberry pie and applying ima_appraise = fix evm = fix to /boot/cmdline.txt</span></span></div><div dir="ltr"><span lang="en"><span title="이후 라즈베리파이를 실행하여 /boot/cmdline.txt 파일에 ima_appraise=fix evm=fix를 적용하여 ima/evm을 생성하였습니다 "><br></span><span title="이후 ima_appraise=enforce, evm=enforce로 변경하여 재부팅하였는데 kernel manager load failed가 발생하였습니다 ">After rebooting with ima_appraise = enforce, evm = enforce, kernel manager load failed</span></span></div><div dir="ltr"><span lang="en"><span title="이후 ima_appraise=enforce, evm=enforce로 변경하여 재부팅하였는데 kernel manager load failed가 발생하였습니다 "><br></span><span title="그래서 labeling을 하였는데 마찬가지로 failed가 발생하였습니다 ">So I did labeling and it failed</span></span></div><div dir="ltr"><span lang="en"><span title="그래서 labeling을 하였는데 마찬가지로 failed가 발생하였습니다 "><br></span><span title="제가 사용한 labeling 코드는 다음과 같습니다 ">Here is the labeling code I used</span></span></div><div dir="ltr"><span lang="en"><span title="제가 사용한 labeling 코드는 다음과 같습니다 "><br></span><span title="sudo find / \( -fstype rootfs -o -fstype ext4 -type f \) -uid 0 -exec head -n 1 '{}' > /dev/null \; ">Sudo find / \ (-fstype rootfs -o -fstype ext4 -type f) -uid 0 -exec head -n 1 '{}'> / dev / null \;</span></span></div><div dir="ltr"><span lang="en"><span title="sudo find / \( -fstype rootfs -o -fstype ext4 -type f \) -uid 0 -exec head -n 1 '{}' > /dev/null \; "><br></span><span title="해당 코드가 맞는지를 알고싶습니다 ">I want to know if the code is correct</span></span></div><div dir="ltr"><span lang="en"><span title="해당 코드가 맞는지를 알고싶습니다 "><br></span><span title="맞다면 코드에 대한 설명을 해주실수 있을까요 ">If so, can you explain the code?</span></span></div><div dir="ltr"><span lang="en"><span title="맞다면 코드에 대한 설명을 해주실수 있을까요 "><br></span><span title="틀리다면 맞는 코드를 알려주세요 ">If wrong, please tell us the correct code</span></span></div><div dir="ltr"><span lang="en"><span title="틀리다면 맞는 코드를 알려주세요 "><br></span><span title="그리고 라벨링이 모든 파일에 ima를 삽입하는 것이 맞나요?">And is labeling correct to put ima in all files? </span><span title="아니면 ima를 적용하기 위한 준비과정같은 것인가요? ">Or is it like preparing to apply ima?</span></span></div><div dir="ltr"><span lang="en"><span title="아니면 ima를 적용하기 위한 준비과정같은 것인가요? "><br></span><span title="이에 대한 설명도 부탁드리겠습니다 ">I would also like to explain this.</span></span></div><div dir="ltr"><span lang="en"><span title="이에 대한 설명도 부탁드리겠습니다 "><br></span><span title="도와주셔서 감사합니다">Thank you for your help</span></span><span id="t-served-community-button" role="button" aria-hidden="true" style="display: none;" unselectable="on"></span></div><p><br></p> <p><br></p></div></td></tr></table> </body> </html> <img id="confirmMailBeacon" src="http://wwl1412.daum.net:4280/@from=sksehwjray%40hanmail.net&rcpt=linux-ima-user%40lists.sourceforge.net&msgid=%3C20170315233346.VFlMqcyeQLu0V7GWWT0dbA%40sksehwjray.hanmail.net%3E"> |
From: Micka <mic...@gm...> - 2017-03-15 14:02:20
|
Do you know where I can find documentation about others PCRs ? which project/binary use those PCRs ? Also why I can't edit this file : "/sys/kernel/security/ima/policy" ? I'm using the root user, but I can't access it. How can I change the policy of the ima ? Micka, Le ven. 10 mars 2017 à 16:31, Ken Goldman <kg...@li...> a écrit : > > On Mon, 2017-03-06 at 11:43 +0000, Micka wrote: > >> > >> Why I have only PCR-10 working in my TPM ? How can I have other PCRs ? > > If your question is "Why does IMA use one PCR? Why not multiple PCRS?" > > PCRs are a scarce resource on the TPM. There are only 24, and most are > already assigned. Generally, one would use multiple PCRs when you want > to seal/unseal to a subset of the measurements. > > Since it's unlikely that one could seal to the IMA measurements (because > multi-threading changes the order each time), I don't see a rationale > for using more than one PCR. > > > > ------------------------------------------------------------------------------ > Announcing the Oxford Dictionaries API! The API offers world-renowned > dictionary content that is easy and intuitive to access. Sign up for an > account today to start using our lexical data to power your apps and > projects. Get started today and enter our developer competition. > http://sdm.link/oxford > _______________________________________________ > Linux-ima-user mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-ima-user > |
From: Ken G. <kg...@li...> - 2017-03-10 15:30:57
|
> On Mon, 2017-03-06 at 11:43 +0000, Micka wrote: >> >> Why I have only PCR-10 working in my TPM ? How can I have other PCRs ? If your question is "Why does IMA use one PCR? Why not multiple PCRS?" PCRs are a scarce resource on the TPM. There are only 24, and most are already assigned. Generally, one would use multiple PCRs when you want to seal/unseal to a subset of the measurements. Since it's unlikely that one could seal to the IMA measurements (because multi-threading changes the order each time), I don't see a rationale for using more than one PCR. |
From: Mimi Z. <zo...@li...> - 2017-03-10 11:24:33
|
On Mon, 2017-03-06 at 11:43 +0000, Micka wrote: > Hi, > > I would like to know what ima-ng template measure ? > > Why I have only PCR-10 working in my TPM ? How can I have other PCRs ? I > heard that you can measure bin file, lib file ? how does it work ? Where is > the list of those files that the IMA will measure ? IMA measures, appraises the integrity, and audits files based on policy. The builtin policy "ima_policy=tcb", which measures files, and the "ima_appraise_tcb", which appraises the integrity of files, can be defined on the boot command line. These builtin policies can be replaced with a custom policy. Refer to Documentation/ABI/testing/ima_policy on how to define a custom policy. IMA has traditionally extended only TPM PCR 10. In some situations, you might want to extend other PCRs. Missing from the documentation is the rule option "pcr=", which allows specifying different pcrs. Mimi |
From: Micka <mic...@gm...> - 2017-03-06 11:43:24
|
Hi, I would like to know what ima-ng template measure ? Why I have only PCR-10 working in my TPM ? How can I have other PCRs ? I heard that you can measure bin file, lib file ? how does it work ? Where is the list of those files that the IMA will measure ? Thanks, Michael Musset. |