Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ima: handle idmapped mounts

IMA does sometimes access the inode's i_uid and compares it against the
rules' fowner. Enable IMA to handle idmapped mounts by passing down the
mount's user namespace. We simply make use of the helpers we introduced
before. If the initial user namespace is passed nothing changes so
non-idmapped mounts will see identical behavior as before.

Link: https://lore.kernel.org/r/20210121131959.646623-27-christian.brauner@ubuntu.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

+83 -49
+1 -1
fs/attr.c
··· 401 401 402 402 if (!error) { 403 403 fsnotify_change(dentry, ia_valid); 404 - ima_inode_post_setattr(dentry); 404 + ima_inode_post_setattr(mnt_userns, dentry); 405 405 evm_inode_post_setattr(dentry, ia_valid); 406 406 } 407 407
+2 -2
fs/namei.c
··· 3422 3422 inode->i_state |= I_LINKABLE; 3423 3423 spin_unlock(&inode->i_lock); 3424 3424 } 3425 - ima_post_create_tmpfile(inode); 3425 + ima_post_create_tmpfile(mnt_userns, inode); 3426 3426 return child; 3427 3427 3428 3428 out_err: ··· 3750 3750 error = vfs_create(mnt_userns, path.dentry->d_inode, 3751 3751 dentry, mode, true); 3752 3752 if (!error) 3753 - ima_post_path_mknod(dentry); 3753 + ima_post_path_mknod(mnt_userns, dentry); 3754 3754 break; 3755 3755 case S_IFCHR: case S_IFBLK: 3756 3756 error = vfs_mknod(mnt_userns, path.dentry->d_inode,
+12 -6
include/linux/ima.h
··· 16 16 #ifdef CONFIG_IMA 17 17 extern int ima_bprm_check(struct linux_binprm *bprm); 18 18 extern int ima_file_check(struct file *file, int mask); 19 - extern void ima_post_create_tmpfile(struct inode *inode); 19 + extern void ima_post_create_tmpfile(struct user_namespace *mnt_userns, 20 + struct inode *inode); 20 21 extern void ima_file_free(struct file *file); 21 22 extern int ima_file_mmap(struct file *file, unsigned long prot); 22 23 extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot); ··· 28 27 bool contents); 29 28 extern int ima_post_read_file(struct file *file, void *buf, loff_t size, 30 29 enum kernel_read_file_id id); 31 - extern void ima_post_path_mknod(struct dentry *dentry); 30 + extern void ima_post_path_mknod(struct user_namespace *mnt_userns, 31 + struct dentry *dentry); 32 32 extern int ima_file_hash(struct file *file, char *buf, size_t buf_size); 33 33 extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size); 34 34 extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size); ··· 70 68 return 0; 71 69 } 72 70 73 - static inline void ima_post_create_tmpfile(struct inode *inode) 71 + static inline void ima_post_create_tmpfile(struct user_namespace *mnt_userns, 72 + struct inode *inode) 74 73 { 75 74 } 76 75 ··· 115 112 return 0; 116 113 } 117 114 118 - static inline void ima_post_path_mknod(struct dentry *dentry) 115 + static inline void ima_post_path_mknod(struct user_namespace *mnt_userns, 116 + struct dentry *dentry) 119 117 { 120 118 return; 121 119 } ··· 157 153 158 154 #ifdef CONFIG_IMA_APPRAISE 159 155 extern bool is_ima_appraise_enabled(void); 160 - extern void ima_inode_post_setattr(struct dentry *dentry); 156 + extern void ima_inode_post_setattr(struct user_namespace *mnt_userns, 157 + struct dentry *dentry); 161 158 extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, 162 159 const void *xattr_value, size_t xattr_value_len); 163 160 extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); ··· 168 163 return 0; 169 164 } 170 165 171 - static inline void ima_inode_post_setattr(struct dentry *dentry) 166 + static inline void ima_inode_post_setattr(struct user_namespace *mnt_userns, 167 + struct dentry *dentry) 172 168 { 173 169 return; 174 170 }
+12 -7
security/integrity/ima/ima.h
··· 253 253 #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */ 254 254 255 255 /* LIM API function definitions */ 256 - int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 257 - int mask, enum ima_hooks func, int *pcr, 256 + int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, 257 + const struct cred *cred, u32 secid, int mask, 258 + enum ima_hooks func, int *pcr, 258 259 struct ima_template_desc **template_desc, 259 260 const char *keyring); 260 261 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); ··· 267 266 struct evm_ima_xattr_data *xattr_value, 268 267 int xattr_len, const struct modsig *modsig, int pcr, 269 268 struct ima_template_desc *template_desc); 270 - void process_buffer_measurement(struct inode *inode, const void *buf, int size, 269 + void process_buffer_measurement(struct user_namespace *mnt_userns, 270 + struct inode *inode, const void *buf, int size, 271 271 const char *eventname, enum ima_hooks func, 272 272 int pcr, const char *keyring); 273 273 void ima_audit_measurement(struct integrity_iint_cache *iint, ··· 283 281 const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); 284 282 285 283 /* IMA policy related functions */ 286 - int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, 287 - enum ima_hooks func, int mask, int flags, int *pcr, 284 + int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, 285 + const struct cred *cred, u32 secid, enum ima_hooks func, 286 + int mask, int flags, int *pcr, 288 287 struct ima_template_desc **template_desc, 289 288 const char *keyring); 290 289 void ima_init_policy(void); ··· 316 313 struct file *file, const unsigned char *filename, 317 314 struct evm_ima_xattr_data *xattr_value, 318 315 int xattr_len, const struct modsig *modsig); 319 - int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); 316 + int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode, 317 + int mask, enum ima_hooks func); 320 318 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); 321 319 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, 322 320 enum ima_hooks func); ··· 344 340 return INTEGRITY_UNKNOWN; 345 341 } 346 342 347 - static inline int ima_must_appraise(struct inode *inode, int mask, 343 + static inline int ima_must_appraise(struct user_namespace *mnt_userns, 344 + struct inode *inode, int mask, 348 345 enum ima_hooks func) 349 346 { 350 347 return 0;
+6 -4
security/integrity/ima/ima_api.c
··· 162 162 163 163 /** 164 164 * ima_get_action - appraise & measure decision based on policy. 165 + * @mnt_userns: user namespace of the mount the inode was found from 165 166 * @inode: pointer to the inode associated with the object being validated 166 167 * @cred: pointer to credentials structure to validate 167 168 * @secid: secid of the task being validated ··· 184 183 * Returns IMA_MEASURE, IMA_APPRAISE mask. 185 184 * 186 185 */ 187 - int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 188 - int mask, enum ima_hooks func, int *pcr, 186 + int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, 187 + const struct cred *cred, u32 secid, int mask, 188 + enum ima_hooks func, int *pcr, 189 189 struct ima_template_desc **template_desc, 190 190 const char *keyring) 191 191 { ··· 194 192 195 193 flags &= ima_policy_flag; 196 194 197 - return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, 198 - template_desc, keyring); 195 + return ima_match_policy(mnt_userns, inode, cred, secid, func, mask, 196 + flags, pcr, template_desc, keyring); 199 197 } 200 198 201 199 /*
+9 -6
security/integrity/ima/ima_appraise.c
··· 68 68 * 69 69 * Return 1 to appraise or hash 70 70 */ 71 - int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) 71 + int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode, 72 + int mask, enum ima_hooks func) 72 73 { 73 74 u32 secid; 74 75 ··· 77 76 return 0; 78 77 79 78 security_task_getsecid(current, &secid); 80 - return ima_match_policy(inode, current_cred(), secid, func, mask, 81 - IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); 79 + return ima_match_policy(mnt_userns, inode, current_cred(), secid, func, 80 + mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); 82 81 } 83 82 84 83 static int ima_fix_xattr(struct dentry *dentry, ··· 351 350 352 351 rc = is_binary_blacklisted(digest, digestsize); 353 352 if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) 354 - process_buffer_measurement(NULL, digest, digestsize, 353 + process_buffer_measurement(&init_user_ns, NULL, digest, digestsize, 355 354 "blacklisted-hash", NONE, 356 355 pcr, NULL); 357 356 } ··· 502 501 503 502 /** 504 503 * ima_inode_post_setattr - reflect file metadata changes 504 + * @mnt_userns: user namespace of the mount the inode was found from 505 505 * @dentry: pointer to the affected dentry 506 506 * 507 507 * Changes to a dentry's metadata might result in needing to appraise. ··· 510 508 * This function is called from notify_change(), which expects the caller 511 509 * to lock the inode's i_mutex. 512 510 */ 513 - void ima_inode_post_setattr(struct dentry *dentry) 511 + void ima_inode_post_setattr(struct user_namespace *mnt_userns, 512 + struct dentry *dentry) 514 513 { 515 514 struct inode *inode = d_backing_inode(dentry); 516 515 struct integrity_iint_cache *iint; ··· 521 518 || !(inode->i_opflags & IOP_XATTR)) 522 519 return; 523 520 524 - action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); 521 + action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR); 525 522 if (!action) 526 523 __vfs_removexattr(&init_user_ns, dentry, XATTR_NAME_IMA); 527 524 iint = integrity_iint_find(inode);
+2 -1
security/integrity/ima/ima_asymmetric_keys.c
··· 10 10 */ 11 11 12 12 #include <keys/asymmetric-type.h> 13 + #include <linux/user_namespace.h> 13 14 #include "ima.h" 14 15 15 16 /** ··· 59 58 * if the IMA policy is configured to measure a key linked 60 59 * to the given keyring. 61 60 */ 62 - process_buffer_measurement(NULL, payload, payload_len, 61 + process_buffer_measurement(&init_user_ns, NULL, payload, payload_len, 63 62 keyring->description, KEY_CHECK, 0, 64 63 keyring->description); 65 64 }
+24 -13
security/integrity/ima/ima_main.c
··· 218 218 * bitmask based on the appraise/audit/measurement policy. 219 219 * Included is the appraise submask. 220 220 */ 221 - action = ima_get_action(inode, cred, secid, mask, func, &pcr, 222 - &template_desc, NULL); 221 + action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid, 222 + mask, func, &pcr, &template_desc, NULL); 223 223 violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && 224 224 (ima_policy_flag & IMA_MEASURE)); 225 225 if (!action && !violation_check) ··· 431 431 432 432 security_task_getsecid(current, &secid); 433 433 inode = file_inode(vma->vm_file); 434 - action = ima_get_action(inode, current_cred(), secid, MAY_EXEC, 435 - MMAP_CHECK, &pcr, &template, 0); 434 + action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode, 435 + current_cred(), secid, MAY_EXEC, MMAP_CHECK, 436 + &pcr, &template, 0); 436 437 437 438 /* Is the mmap'ed file in policy? */ 438 439 if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) ··· 593 592 594 593 /** 595 594 * ima_post_create_tmpfile - mark newly created tmpfile as new 595 + * @mnt_userns: user namespace of the mount the inode was found from 596 596 * @file : newly created tmpfile 597 597 * 598 598 * No measuring, appraising or auditing of newly created tmpfiles is needed. 599 599 * Skip calling process_measurement(), but indicate which newly, created 600 600 * tmpfiles are in policy. 601 601 */ 602 - void ima_post_create_tmpfile(struct inode *inode) 602 + void ima_post_create_tmpfile(struct user_namespace *mnt_userns, 603 + struct inode *inode) 603 604 { 604 605 struct integrity_iint_cache *iint; 605 606 int must_appraise; 606 607 607 - must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK); 608 + must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, 609 + FILE_CHECK); 608 610 if (!must_appraise) 609 611 return; 610 612 ··· 623 619 624 620 /** 625 621 * ima_post_path_mknod - mark as a new inode 622 + * @mnt_userns: user namespace of the mount the inode was found from 626 623 * @dentry: newly created dentry 627 624 * 628 625 * Mark files created via the mknodat syscall as new, so that the 629 626 * file data can be written later. 630 627 */ 631 - void ima_post_path_mknod(struct dentry *dentry) 628 + void ima_post_path_mknod(struct user_namespace *mnt_userns, 629 + struct dentry *dentry) 632 630 { 633 631 struct integrity_iint_cache *iint; 634 632 struct inode *inode = dentry->d_inode; 635 633 int must_appraise; 636 634 637 - must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK); 635 + must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, 636 + FILE_CHECK); 638 637 if (!must_appraise) 639 638 return; 640 639 ··· 817 810 818 811 /* 819 812 * process_buffer_measurement - Measure the buffer to ima log. 813 + * @mnt_userns: user namespace of the mount the inode was found from 820 814 * @inode: inode associated with the object being measured (NULL for KEY_CHECK) 821 815 * @buf: pointer to the buffer that needs to be added to the log. 822 816 * @size: size of buffer(in bytes). ··· 828 820 * 829 821 * Based on policy, the buffer is measured into the ima log. 830 822 */ 831 - void process_buffer_measurement(struct inode *inode, const void *buf, int size, 823 + void process_buffer_measurement(struct user_namespace *mnt_userns, 824 + struct inode *inode, const void *buf, int size, 832 825 const char *eventname, enum ima_hooks func, 833 826 int pcr, const char *keyring) 834 827 { ··· 869 860 */ 870 861 if (func) { 871 862 security_task_getsecid(current, &secid); 872 - action = ima_get_action(inode, current_cred(), secid, 0, func, 873 - &pcr, &template, keyring); 863 + action = ima_get_action(mnt_userns, inode, current_cred(), 864 + secid, 0, func, &pcr, &template, 865 + keyring); 874 866 if (!(action & IMA_MEASURE)) 875 867 return; 876 868 } ··· 929 919 if (!f.file) 930 920 return; 931 921 932 - process_buffer_measurement(file_inode(f.file), buf, size, 933 - "kexec-cmdline", KEXEC_CMDLINE, 0, NULL); 922 + process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file), 923 + buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, 924 + NULL); 934 925 fdput(f); 935 926 } 936 927
+12 -8
security/integrity/ima/ima_policy.c
··· 488 488 /** 489 489 * ima_match_rules - determine whether an inode matches the policy rule. 490 490 * @rule: a pointer to a rule 491 + * @mnt_userns: user namespace of the mount the inode was found from 491 492 * @inode: a pointer to an inode 492 493 * @cred: a pointer to a credentials structure for user validation 493 494 * @secid: the secid of the task to be validated ··· 498 497 * 499 498 * Returns true on rule match, false on failure. 500 499 */ 501 - static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, 502 - const struct cred *cred, u32 secid, 503 - enum ima_hooks func, int mask, 500 + static bool ima_match_rules(struct ima_rule_entry *rule, 501 + struct user_namespace *mnt_userns, 502 + struct inode *inode, const struct cred *cred, 503 + u32 secid, enum ima_hooks func, int mask, 504 504 const char *keyring) 505 505 { 506 506 int i; ··· 541 539 } 542 540 543 541 if ((rule->flags & IMA_FOWNER) && 544 - !rule->fowner_op(inode->i_uid, rule->fowner)) 542 + !rule->fowner_op(i_uid_into_mnt(mnt_userns, inode), rule->fowner)) 545 543 return false; 546 544 for (i = 0; i < MAX_LSM_RULES; i++) { 547 545 int rc = 0; ··· 604 602 605 603 /** 606 604 * ima_match_policy - decision based on LSM and other conditions 605 + * @mnt_userns: user namespace of the mount the inode was found from 607 606 * @inode: pointer to an inode for which the policy decision is being made 608 607 * @cred: pointer to a credentials structure for which the policy decision is 609 608 * being made ··· 623 620 * list when walking it. Reads are many orders of magnitude more numerous 624 621 * than writes so ima_match_policy() is classical RCU candidate. 625 622 */ 626 - int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, 627 - enum ima_hooks func, int mask, int flags, int *pcr, 623 + int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, 624 + const struct cred *cred, u32 secid, enum ima_hooks func, 625 + int mask, int flags, int *pcr, 628 626 struct ima_template_desc **template_desc, 629 627 const char *keyring) 630 628 { ··· 641 637 if (!(entry->action & actmask)) 642 638 continue; 643 639 644 - if (!ima_match_rules(entry, inode, cred, secid, func, mask, 645 - keyring)) 640 + if (!ima_match_rules(entry, mnt_userns, inode, cred, secid, 641 + func, mask, keyring)) 646 642 continue; 647 643 648 644 action |= entry->flags & IMA_ACTION_FLAGS;
+3 -1
security/integrity/ima/ima_queue_keys.c
··· 8 8 * Enables deferred processing of keys 9 9 */ 10 10 11 + #include <linux/user_namespace.h> 11 12 #include <linux/workqueue.h> 12 13 #include <keys/asymmetric-type.h> 13 14 #include "ima.h" ··· 159 158 160 159 list_for_each_entry_safe(entry, tmp, &ima_keys, list) { 161 160 if (!timer_expired) 162 - process_buffer_measurement(NULL, entry->payload, 161 + process_buffer_measurement(&init_user_ns, NULL, 162 + entry->payload, 163 163 entry->payload_len, 164 164 entry->keyring_name, 165 165 KEY_CHECK, 0,