diff options
author | James Morris <jmorris@namei.org> | 2010-05-17 18:57:00 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-17 18:57:00 -0400 |
commit | 539c99fd7fc28f8db257c713c10fb4aceadf8887 (patch) | |
tree | e603e48ac816cde56e4872e0f7bcdfe7bd33f3b3 | |
parent | ba2e1c5f25a99dec3873745031ad23ce3fd79bff (diff) | |
parent | 4d09ec0f705cf88a12add029c058b53f288cfaa2 (diff) |
Merge branch 'next' into for-linus
57 files changed, 1246 insertions, 1061 deletions
diff --git a/Documentation/credentials.txt b/Documentation/credentials.txt index df03169782ea..a2db35287003 100644 --- a/Documentation/credentials.txt +++ b/Documentation/credentials.txt | |||
@@ -408,9 +408,6 @@ This should be used inside the RCU read lock, as in the following example: | |||
408 | ... | 408 | ... |
409 | } | 409 | } |
410 | 410 | ||
411 | A function need not get RCU read lock to use __task_cred() if it is holding a | ||
412 | spinlock at the time as this implicitly holds the RCU read lock. | ||
413 | |||
414 | Should it be necessary to hold another task's credentials for a long period of | 411 | Should it be necessary to hold another task's credentials for a long period of |
415 | time, and possibly to sleep whilst doing so, then the caller should get a | 412 | time, and possibly to sleep whilst doing so, then the caller should get a |
416 | reference on them using: | 413 | reference on them using: |
@@ -426,17 +423,16 @@ credentials, hiding the RCU magic from the caller: | |||
426 | uid_t task_uid(task) Task's real UID | 423 | uid_t task_uid(task) Task's real UID |
427 | uid_t task_euid(task) Task's effective UID | 424 | uid_t task_euid(task) Task's effective UID |
428 | 425 | ||
429 | If the caller is holding a spinlock or the RCU read lock at the time anyway, | 426 | If the caller is holding the RCU read lock at the time anyway, then: |
430 | then: | ||
431 | 427 | ||
432 | __task_cred(task)->uid | 428 | __task_cred(task)->uid |
433 | __task_cred(task)->euid | 429 | __task_cred(task)->euid |
434 | 430 | ||
435 | should be used instead. Similarly, if multiple aspects of a task's credentials | 431 | should be used instead. Similarly, if multiple aspects of a task's credentials |
436 | need to be accessed, RCU read lock or a spinlock should be used, __task_cred() | 432 | need to be accessed, RCU read lock should be used, __task_cred() called, the |
437 | called, the result stored in a temporary pointer and then the credential | 433 | result stored in a temporary pointer and then the credential aspects called |
438 | aspects called from that before dropping the lock. This prevents the | 434 | from that before dropping the lock. This prevents the potentially expensive |
439 | potentially expensive RCU magic from being invoked multiple times. | 435 | RCU magic from being invoked multiple times. |
440 | 436 | ||
441 | Should some other single aspect of another task's credentials need to be | 437 | Should some other single aspect of another task's credentials need to be |
442 | accessed, then this can be used: | 438 | accessed, then this can be used: |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 839b21b0699a..db1db1ea3c0a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -99,6 +99,7 @@ parameter is applicable: | |||
99 | SWSUSP Software suspend (hibernation) is enabled. | 99 | SWSUSP Software suspend (hibernation) is enabled. |
100 | SUSPEND System suspend states are enabled. | 100 | SUSPEND System suspend states are enabled. |
101 | FTRACE Function tracing enabled. | 101 | FTRACE Function tracing enabled. |
102 | TPM TPM drivers are enabled. | ||
102 | TS Appropriate touchscreen support is enabled. | 103 | TS Appropriate touchscreen support is enabled. |
103 | UMS USB Mass Storage support is enabled. | 104 | UMS USB Mass Storage support is enabled. |
104 | USB USB support is enabled. | 105 | USB USB support is enabled. |
@@ -2610,6 +2611,15 @@ and is between 256 and 4096 characters. It is defined in the file | |||
2610 | 2611 | ||
2611 | tp720= [HW,PS2] | 2612 | tp720= [HW,PS2] |
2612 | 2613 | ||
2614 | tpm_suspend_pcr=[HW,TPM] | ||
2615 | Format: integer pcr id | ||
2616 | Specify that at suspend time, the tpm driver | ||
2617 | should extend the specified pcr with zeros, | ||
2618 | as a workaround for some chips which fail to | ||
2619 | flush the last written pcr on TPM_SaveState. | ||
2620 | This will guarantee that all the other pcrs | ||
2621 | are saved. | ||
2622 | |||
2613 | trace_buf_size=nn[KMG] | 2623 | trace_buf_size=nn[KMG] |
2614 | [FTRACE] will set tracing buffer size. | 2624 | [FTRACE] will set tracing buffer size. |
2615 | 2625 | ||
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index f5fc64f89c5c..4dc338f3d1aa 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -17,14 +17,16 @@ menuconfig TCG_TPM | |||
17 | obtained at: <http://sourceforge.net/projects/trousers>. To | 17 | obtained at: <http://sourceforge.net/projects/trousers>. To |
18 | compile this driver as a module, choose M here; the module | 18 | compile this driver as a module, choose M here; the module |
19 | will be called tpm. If unsure, say N. | 19 | will be called tpm. If unsure, say N. |
20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 20 | Notes: |
21 | 1) For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | ||
21 | and CONFIG_PNPACPI. | 22 | and CONFIG_PNPACPI. |
23 | 2) Without ACPI enabled, the BIOS event log won't be accessible, | ||
24 | which is required to validate the PCR 0-7 values. | ||
22 | 25 | ||
23 | if TCG_TPM | 26 | if TCG_TPM |
24 | 27 | ||
25 | config TCG_TIS | 28 | config TCG_TIS |
26 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
27 | depends on PNP | ||
28 | ---help--- | 30 | ---help--- |
29 | If you have a TPM security chip that is compliant with the | 31 | If you have a TPM security chip that is compliant with the |
30 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 068c816e6942..05ad4a17a28f 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1068,6 +1068,27 @@ void tpm_remove_hardware(struct device *dev) | |||
1068 | } | 1068 | } |
1069 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1069 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1070 | 1070 | ||
1071 | #define TPM_ORD_SAVESTATE cpu_to_be32(152) | ||
1072 | #define SAVESTATE_RESULT_SIZE 10 | ||
1073 | |||
1074 | static struct tpm_input_header savestate_header = { | ||
1075 | .tag = TPM_TAG_RQU_COMMAND, | ||
1076 | .length = cpu_to_be32(10), | ||
1077 | .ordinal = TPM_ORD_SAVESTATE | ||
1078 | }; | ||
1079 | |||
1080 | /* Bug workaround - some TPM's don't flush the most | ||
1081 | * recently changed pcr on suspend, so force the flush | ||
1082 | * with an extend to the selected _unused_ non-volatile pcr. | ||
1083 | */ | ||
1084 | static int tpm_suspend_pcr; | ||
1085 | static int __init tpm_suspend_setup(char *str) | ||
1086 | { | ||
1087 | get_option(&str, &tpm_suspend_pcr); | ||
1088 | return 1; | ||
1089 | } | ||
1090 | __setup("tpm_suspend_pcr=", tpm_suspend_setup); | ||
1091 | |||
1071 | /* | 1092 | /* |
1072 | * We are about to suspend. Save the TPM state | 1093 | * We are about to suspend. Save the TPM state |
1073 | * so that it can be restored. | 1094 | * so that it can be restored. |
@@ -1075,17 +1096,29 @@ EXPORT_SYMBOL_GPL(tpm_remove_hardware); | |||
1075 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) | 1096 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) |
1076 | { | 1097 | { |
1077 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1098 | struct tpm_chip *chip = dev_get_drvdata(dev); |
1078 | u8 savestate[] = { | 1099 | struct tpm_cmd_t cmd; |
1079 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 1100 | int rc; |
1080 | 0, 0, 0, 10, /* blob length (in bytes) */ | 1101 | |
1081 | 0, 0, 0, 152 /* TPM_ORD_SaveState */ | 1102 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; |
1082 | }; | ||
1083 | 1103 | ||
1084 | if (chip == NULL) | 1104 | if (chip == NULL) |
1085 | return -ENODEV; | 1105 | return -ENODEV; |
1086 | 1106 | ||
1087 | tpm_transmit(chip, savestate, sizeof(savestate)); | 1107 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
1088 | return 0; | 1108 | if (tpm_suspend_pcr) { |
1109 | cmd.header.in = pcrextend_header; | ||
1110 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | ||
1111 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | ||
1112 | TPM_DIGEST_SIZE); | ||
1113 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | ||
1114 | "extending dummy pcr before suspend"); | ||
1115 | } | ||
1116 | |||
1117 | /* now do the actual savestate */ | ||
1118 | cmd.header.in = savestate_header; | ||
1119 | rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, | ||
1120 | "sending savestate before suspend"); | ||
1121 | return rc; | ||
1089 | } | 1122 | } |
1090 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); | 1123 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); |
1091 | 1124 | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 94345994f8a6..24314a9cffe8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -598,7 +598,7 @@ out_err: | |||
598 | tpm_remove_hardware(chip->dev); | 598 | tpm_remove_hardware(chip->dev); |
599 | return rc; | 599 | return rc; |
600 | } | 600 | } |
601 | 601 | #ifdef CONFIG_PNP | |
602 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 602 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
603 | const struct pnp_device_id *pnp_id) | 603 | const struct pnp_device_id *pnp_id) |
604 | { | 604 | { |
@@ -663,7 +663,7 @@ static struct pnp_driver tis_pnp_driver = { | |||
663 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | 663 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, |
664 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 664 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
665 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 665 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
666 | 666 | #endif | |
667 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) | 667 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) |
668 | { | 668 | { |
669 | return tpm_pm_suspend(&dev->dev, msg); | 669 | return tpm_pm_suspend(&dev->dev, msg); |
@@ -690,21 +690,21 @@ MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | |||
690 | static int __init init_tis(void) | 690 | static int __init init_tis(void) |
691 | { | 691 | { |
692 | int rc; | 692 | int rc; |
693 | #ifdef CONFIG_PNP | ||
694 | if (!force) | ||
695 | return pnp_register_driver(&tis_pnp_driver); | ||
696 | #endif | ||
693 | 697 | ||
694 | if (force) { | 698 | rc = platform_driver_register(&tis_drv); |
695 | rc = platform_driver_register(&tis_drv); | 699 | if (rc < 0) |
696 | if (rc < 0) | ||
697 | return rc; | ||
698 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
699 | return PTR_ERR(pdev); | ||
700 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
701 | platform_device_unregister(pdev); | ||
702 | platform_driver_unregister(&tis_drv); | ||
703 | } | ||
704 | return rc; | 700 | return rc; |
701 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
702 | return PTR_ERR(pdev); | ||
703 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
704 | platform_device_unregister(pdev); | ||
705 | platform_driver_unregister(&tis_drv); | ||
705 | } | 706 | } |
706 | 707 | return rc; | |
707 | return pnp_register_driver(&tis_pnp_driver); | ||
708 | } | 708 | } |
709 | 709 | ||
710 | static void __exit cleanup_tis(void) | 710 | static void __exit cleanup_tis(void) |
@@ -728,12 +728,14 @@ static void __exit cleanup_tis(void) | |||
728 | list_del(&i->list); | 728 | list_del(&i->list); |
729 | } | 729 | } |
730 | spin_unlock(&tis_lock); | 730 | spin_unlock(&tis_lock); |
731 | 731 | #ifdef CONFIG_PNP | |
732 | if (force) { | 732 | if (!force) { |
733 | platform_device_unregister(pdev); | ||
734 | platform_driver_unregister(&tis_drv); | ||
735 | } else | ||
736 | pnp_unregister_driver(&tis_pnp_driver); | 733 | pnp_unregister_driver(&tis_pnp_driver); |
734 | return; | ||
735 | } | ||
736 | #endif | ||
737 | platform_device_unregister(pdev); | ||
738 | platform_driver_unregister(&tis_drv); | ||
737 | } | 739 | } |
738 | 740 | ||
739 | module_init(init_tis); | 741 | module_init(init_tis); |
diff --git a/fs/inode.c b/fs/inode.c index 407bf392e20a..258ec22bb298 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1205,8 +1205,6 @@ void generic_delete_inode(struct inode *inode) | |||
1205 | inodes_stat.nr_inodes--; | 1205 | inodes_stat.nr_inodes--; |
1206 | spin_unlock(&inode_lock); | 1206 | spin_unlock(&inode_lock); |
1207 | 1207 | ||
1208 | security_inode_delete(inode); | ||
1209 | |||
1210 | if (op->delete_inode) { | 1208 | if (op->delete_inode) { |
1211 | void (*delete)(struct inode *) = op->delete_inode; | 1209 | void (*delete)(struct inode *) = op->delete_inode; |
1212 | /* Filesystems implementing their own | 1210 | /* Filesystems implementing their own |
diff --git a/fs/namespace.c b/fs/namespace.c index f20cb57d1067..88058de59c7c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -628,7 +628,6 @@ repeat: | |||
628 | mnt->mnt_pinned = 0; | 628 | mnt->mnt_pinned = 0; |
629 | spin_unlock(&vfsmount_lock); | 629 | spin_unlock(&vfsmount_lock); |
630 | acct_auto_close_mnt(mnt); | 630 | acct_auto_close_mnt(mnt); |
631 | security_sb_umount_close(mnt); | ||
632 | goto repeat; | 631 | goto repeat; |
633 | } | 632 | } |
634 | } | 633 | } |
@@ -1117,8 +1116,6 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
1117 | retval = 0; | 1116 | retval = 0; |
1118 | } | 1117 | } |
1119 | spin_unlock(&vfsmount_lock); | 1118 | spin_unlock(&vfsmount_lock); |
1120 | if (retval) | ||
1121 | security_sb_umount_busy(mnt); | ||
1122 | up_write(&namespace_sem); | 1119 | up_write(&namespace_sem); |
1123 | release_mounts(&umount_list); | 1120 | release_mounts(&umount_list); |
1124 | return retval; | 1121 | return retval; |
@@ -1435,17 +1432,10 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) | |||
1435 | if (cant_mount(path->dentry)) | 1432 | if (cant_mount(path->dentry)) |
1436 | goto out_unlock; | 1433 | goto out_unlock; |
1437 | 1434 | ||
1438 | err = security_sb_check_sb(mnt, path); | ||
1439 | if (err) | ||
1440 | goto out_unlock; | ||
1441 | |||
1442 | err = -ENOENT; | ||
1443 | if (!d_unlinked(path->dentry)) | 1435 | if (!d_unlinked(path->dentry)) |
1444 | err = attach_recursive_mnt(mnt, path, NULL); | 1436 | err = attach_recursive_mnt(mnt, path, NULL); |
1445 | out_unlock: | 1437 | out_unlock: |
1446 | mutex_unlock(&path->dentry->d_inode->i_mutex); | 1438 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
1447 | if (!err) | ||
1448 | security_sb_post_addmount(mnt, path); | ||
1449 | return err; | 1439 | return err; |
1450 | } | 1440 | } |
1451 | 1441 | ||
@@ -1581,8 +1571,6 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1581 | } | 1571 | } |
1582 | up_write(&sb->s_umount); | 1572 | up_write(&sb->s_umount); |
1583 | if (!err) { | 1573 | if (!err) { |
1584 | security_sb_post_remount(path->mnt, flags, data); | ||
1585 | |||
1586 | spin_lock(&vfsmount_lock); | 1574 | spin_lock(&vfsmount_lock); |
1587 | touch_mnt_namespace(path->mnt->mnt_ns); | 1575 | touch_mnt_namespace(path->mnt->mnt_ns); |
1588 | spin_unlock(&vfsmount_lock); | 1576 | spin_unlock(&vfsmount_lock); |
@@ -2277,7 +2265,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2277 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2265 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
2278 | spin_unlock(&vfsmount_lock); | 2266 | spin_unlock(&vfsmount_lock); |
2279 | chroot_fs_refs(&root, &new); | 2267 | chroot_fs_refs(&root, &new); |
2280 | security_sb_post_pivotroot(&root, &new); | ||
2281 | error = 0; | 2268 | error = 0; |
2282 | path_put(&root_parent); | 2269 | path_put(&root_parent); |
2283 | path_put(&parent_path); | 2270 | path_put(&parent_path); |
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index f78f83d7663f..6907251d5200 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h | |||
@@ -33,7 +33,7 @@ struct common_audit_data { | |||
33 | #define LSM_AUDIT_DATA_IPC 4 | 33 | #define LSM_AUDIT_DATA_IPC 4 |
34 | #define LSM_AUDIT_DATA_TASK 5 | 34 | #define LSM_AUDIT_DATA_TASK 5 |
35 | #define LSM_AUDIT_DATA_KEY 6 | 35 | #define LSM_AUDIT_DATA_KEY 6 |
36 | #define LSM_AUDIT_NO_AUDIT 7 | 36 | #define LSM_AUDIT_DATA_NONE 7 |
37 | #define LSM_AUDIT_DATA_KMOD 8 | 37 | #define LSM_AUDIT_DATA_KMOD 8 |
38 | struct task_struct *tsk; | 38 | struct task_struct *tsk; |
39 | union { | 39 | union { |
diff --git a/include/linux/security.h b/include/linux/security.h index 3158dd982d27..0c8819170463 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -267,49 +267,16 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
267 | * @orig the original mount data copied from userspace. | 267 | * @orig the original mount data copied from userspace. |
268 | * @copy copied data which will be passed to the security module. | 268 | * @copy copied data which will be passed to the security module. |
269 | * Returns 0 if the copy was successful. | 269 | * Returns 0 if the copy was successful. |
270 | * @sb_check_sb: | ||
271 | * Check permission before the device with superblock @mnt->sb is mounted | ||
272 | * on the mount point named by @nd. | ||
273 | * @mnt contains the vfsmount for device being mounted. | ||
274 | * @path contains the path for the mount point. | ||
275 | * Return 0 if permission is granted. | ||
276 | * @sb_umount: | 270 | * @sb_umount: |
277 | * Check permission before the @mnt file system is unmounted. | 271 | * Check permission before the @mnt file system is unmounted. |
278 | * @mnt contains the mounted file system. | 272 | * @mnt contains the mounted file system. |
279 | * @flags contains the unmount flags, e.g. MNT_FORCE. | 273 | * @flags contains the unmount flags, e.g. MNT_FORCE. |
280 | * Return 0 if permission is granted. | 274 | * Return 0 if permission is granted. |
281 | * @sb_umount_close: | ||
282 | * Close any files in the @mnt mounted filesystem that are held open by | ||
283 | * the security module. This hook is called during an umount operation | ||
284 | * prior to checking whether the filesystem is still busy. | ||
285 | * @mnt contains the mounted filesystem. | ||
286 | * @sb_umount_busy: | ||
287 | * Handle a failed umount of the @mnt mounted filesystem, e.g. re-opening | ||
288 | * any files that were closed by umount_close. This hook is called during | ||
289 | * an umount operation if the umount fails after a call to the | ||
290 | * umount_close hook. | ||
291 | * @mnt contains the mounted filesystem. | ||
292 | * @sb_post_remount: | ||
293 | * Update the security module's state when a filesystem is remounted. | ||
294 | * This hook is only called if the remount was successful. | ||
295 | * @mnt contains the mounted file system. | ||
296 | * @flags contains the new filesystem flags. | ||
297 | * @data contains the filesystem-specific data. | ||
298 | * @sb_post_addmount: | ||
299 | * Update the security module's state when a filesystem is mounted. | ||
300 | * This hook is called any time a mount is successfully grafetd to | ||
301 | * the tree. | ||
302 | * @mnt contains the mounted filesystem. | ||
303 | * @mountpoint contains the path for the mount point. | ||
304 | * @sb_pivotroot: | 275 | * @sb_pivotroot: |
305 | * Check permission before pivoting the root filesystem. | 276 | * Check permission before pivoting the root filesystem. |
306 | * @old_path contains the path for the new location of the current root (put_old). | 277 | * @old_path contains the path for the new location of the current root (put_old). |
307 | * @new_path contains the path for the new root (new_root). | 278 | * @new_path contains the path for the new root (new_root). |
308 | * Return 0 if permission is granted. | 279 | * Return 0 if permission is granted. |
309 | * @sb_post_pivotroot: | ||
310 | * Update module state after a successful pivot. | ||
311 | * @old_path contains the path for the old root. | ||
312 | * @new_path contains the path for the new root. | ||
313 | * @sb_set_mnt_opts: | 280 | * @sb_set_mnt_opts: |
314 | * Set the security relevant mount options used for a superblock | 281 | * Set the security relevant mount options used for a superblock |
315 | * @sb the superblock to set security mount options for | 282 | * @sb the superblock to set security mount options for |
@@ -511,12 +478,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
511 | * @mnt is the vfsmount where the dentry was looked up | 478 | * @mnt is the vfsmount where the dentry was looked up |
512 | * @dentry contains the dentry structure for the file. | 479 | * @dentry contains the dentry structure for the file. |
513 | * Return 0 if permission is granted. | 480 | * Return 0 if permission is granted. |
514 | * @inode_delete: | ||
515 | * @inode contains the inode structure for deleted inode. | ||
516 | * This hook is called when a deleted inode is released (i.e. an inode | ||
517 | * with no hard links has its use count drop to zero). A security module | ||
518 | * can use this hook to release any persistent label associated with the | ||
519 | * inode. | ||
520 | * @inode_setxattr: | 481 | * @inode_setxattr: |
521 | * Check permission before setting the extended attributes | 482 | * Check permission before setting the extended attributes |
522 | * @value identified by @name for @dentry. | 483 | * @value identified by @name for @dentry. |
@@ -691,10 +652,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
691 | * @old points to the original credentials. | 652 | * @old points to the original credentials. |
692 | * @gfp indicates the atomicity of any memory allocations. | 653 | * @gfp indicates the atomicity of any memory allocations. |
693 | * Prepare a new set of credentials by copying the data from the old set. | 654 | * Prepare a new set of credentials by copying the data from the old set. |
694 | * @cred_commit: | ||
695 | * @new points to the new credentials. | ||
696 | * @old points to the original credentials. | ||
697 | * Install a new set of credentials. | ||
698 | * @cred_transfer: | 655 | * @cred_transfer: |
699 | * @new points to the new credentials. | 656 | * @new points to the new credentials. |
700 | * @old points to the original credentials. | 657 | * @old points to the original credentials. |
@@ -717,18 +674,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
717 | * userspace to load a kernel module with the given name. | 674 | * userspace to load a kernel module with the given name. |
718 | * @kmod_name name of the module requested by the kernel | 675 | * @kmod_name name of the module requested by the kernel |
719 | * Return 0 if successful. | 676 | * Return 0 if successful. |
720 | * @task_setuid: | ||
721 | * Check permission before setting one or more of the user identity | ||
722 | * attributes of the current process. The @flags parameter indicates | ||
723 | * which of the set*uid system calls invoked this hook and how to | ||
724 | * interpret the @id0, @id1, and @id2 parameters. See the LSM_SETID | ||
725 | * definitions at the beginning of this file for the @flags values and | ||
726 | * their meanings. | ||
727 | * @id0 contains a uid. | ||
728 | * @id1 contains a uid. | ||
729 | * @id2 contains a uid. | ||
730 | * @flags contains one of the LSM_SETID_* values. | ||
731 | * Return 0 if permission is granted. | ||
732 | * @task_fix_setuid: | 677 | * @task_fix_setuid: |
733 | * Update the module's state after setting one or more of the user | 678 | * Update the module's state after setting one or more of the user |
734 | * identity attributes of the current process. The @flags parameter | 679 | * identity attributes of the current process. The @flags parameter |
@@ -738,18 +683,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
738 | * @old is the set of credentials that are being replaces | 683 | * @old is the set of credentials that are being replaces |
739 | * @flags contains one of the LSM_SETID_* values. | 684 | * @flags contains one of the LSM_SETID_* values. |
740 | * Return 0 on success. | 685 | * Return 0 on success. |
741 | * @task_setgid: | ||
742 | * Check permission before setting one or more of the group identity | ||
743 | * attributes of the current process. The @flags parameter indicates | ||
744 | * which of the set*gid system calls invoked this hook and how to | ||
745 | * interpret the @id0, @id1, and @id2 parameters. See the LSM_SETID | ||
746 | * definitions at the beginning of this file for the @flags values and | ||
747 | * their meanings. | ||
748 | * @id0 contains a gid. | ||
749 | * @id1 contains a gid. | ||
750 | * @id2 contains a gid. | ||
751 | * @flags contains one of the LSM_SETID_* values. | ||
752 | * Return 0 if permission is granted. | ||
753 | * @task_setpgid: | 686 | * @task_setpgid: |
754 | * Check permission before setting the process group identifier of the | 687 | * Check permission before setting the process group identifier of the |
755 | * process @p to @pgid. | 688 | * process @p to @pgid. |
@@ -771,11 +704,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
771 | * @p contains the task_struct for the process and place is into @secid. | 704 | * @p contains the task_struct for the process and place is into @secid. |
772 | * In case of failure, @secid will be set to zero. | 705 | * In case of failure, @secid will be set to zero. |
773 | * | 706 | * |
774 | * @task_setgroups: | ||
775 | * Check permission before setting the supplementary group set of the | ||
776 | * current process. | ||
777 | * @group_info contains the new group information. | ||
778 | * Return 0 if permission is granted. | ||
779 | * @task_setnice: | 707 | * @task_setnice: |
780 | * Check permission before setting the nice value of @p to @nice. | 708 | * Check permission before setting the nice value of @p to @nice. |
781 | * @p contains the task_struct of process. | 709 | * @p contains the task_struct of process. |
@@ -1139,13 +1067,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1139 | * Return the length of the string (including terminating NUL) or -ve if | 1067 | * Return the length of the string (including terminating NUL) or -ve if |
1140 | * an error. | 1068 | * an error. |
1141 | * May also return 0 (and a NULL buffer pointer) if there is no label. | 1069 | * May also return 0 (and a NULL buffer pointer) if there is no label. |
1142 | * @key_session_to_parent: | ||
1143 | * Forcibly assign the session keyring from a process to its parent | ||
1144 | * process. | ||
1145 | * @cred: Pointer to process's credentials | ||
1146 | * @parent_cred: Pointer to parent process's credentials | ||
1147 | * @keyring: Proposed new session keyring | ||
1148 | * Return 0 if permission is granted, -ve error otherwise. | ||
1149 | * | 1070 | * |
1150 | * Security hooks affecting all System V IPC operations. | 1071 | * Security hooks affecting all System V IPC operations. |
1151 | * | 1072 | * |
@@ -1333,13 +1254,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1333 | * @cap contains the capability <include/linux/capability.h>. | 1254 | * @cap contains the capability <include/linux/capability.h>. |
1334 | * @audit: Whether to write an audit message or not | 1255 | * @audit: Whether to write an audit message or not |
1335 | * Return 0 if the capability is granted for @tsk. | 1256 | * Return 0 if the capability is granted for @tsk. |
1336 | * @acct: | ||
1337 | * Check permission before enabling or disabling process accounting. If | ||
1338 | * accounting is being enabled, then @file refers to the open file used to | ||
1339 | * store accounting records. If accounting is being disabled, then @file | ||
1340 | * is NULL. | ||
1341 | * @file contains the file structure for the accounting file (may be NULL). | ||
1342 | * Return 0 if permission is granted. | ||
1343 | * @sysctl: | 1257 | * @sysctl: |
1344 | * Check permission before accessing the @table sysctl variable in the | 1258 | * Check permission before accessing the @table sysctl variable in the |
1345 | * manner specified by @op. | 1259 | * manner specified by @op. |
@@ -1462,7 +1376,6 @@ struct security_operations { | |||
1462 | const kernel_cap_t *permitted); | 1376 | const kernel_cap_t *permitted); |
1463 | int (*capable) (struct task_struct *tsk, const struct cred *cred, | 1377 | int (*capable) (struct task_struct *tsk, const struct cred *cred, |
1464 | int cap, int audit); | 1378 | int cap, int audit); |
1465 | int (*acct) (struct file *file); | ||
1466 | int (*sysctl) (struct ctl_table *table, int op); | 1379 | int (*sysctl) (struct ctl_table *table, int op); |
1467 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); | 1380 | int (*quotactl) (int cmds, int type, int id, struct super_block *sb); |
1468 | int (*quota_on) (struct dentry *dentry); | 1381 | int (*quota_on) (struct dentry *dentry); |
@@ -1484,18 +1397,9 @@ struct security_operations { | |||
1484 | int (*sb_statfs) (struct dentry *dentry); | 1397 | int (*sb_statfs) (struct dentry *dentry); |
1485 | int (*sb_mount) (char *dev_name, struct path *path, | 1398 | int (*sb_mount) (char *dev_name, struct path *path, |
1486 | char *type, unsigned long flags, void *data); | 1399 | char *type, unsigned long flags, void *data); |
1487 | int (*sb_check_sb) (struct vfsmount *mnt, struct path *path); | ||
1488 | int (*sb_umount) (struct vfsmount *mnt, int flags); | 1400 | int (*sb_umount) (struct vfsmount *mnt, int flags); |
1489 | void (*sb_umount_close) (struct vfsmount *mnt); | ||
1490 | void (*sb_umount_busy) (struct vfsmount *mnt); | ||
1491 | void (*sb_post_remount) (struct vfsmount *mnt, | ||
1492 | unsigned long flags, void *data); | ||
1493 | void (*sb_post_addmount) (struct vfsmount *mnt, | ||
1494 | struct path *mountpoint); | ||
1495 | int (*sb_pivotroot) (struct path *old_path, | 1401 | int (*sb_pivotroot) (struct path *old_path, |
1496 | struct path *new_path); | 1402 | struct path *new_path); |
1497 | void (*sb_post_pivotroot) (struct path *old_path, | ||
1498 | struct path *new_path); | ||
1499 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1403 | int (*sb_set_mnt_opts) (struct super_block *sb, |
1500 | struct security_mnt_opts *opts); | 1404 | struct security_mnt_opts *opts); |
1501 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, | 1405 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, |
@@ -1544,7 +1448,6 @@ struct security_operations { | |||
1544 | int (*inode_permission) (struct inode *inode, int mask); | 1448 | int (*inode_permission) (struct inode *inode, int mask); |
1545 | int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); | 1449 | int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); |
1546 | int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); | 1450 | int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); |
1547 | void (*inode_delete) (struct inode *inode); | ||
1548 | int (*inode_setxattr) (struct dentry *dentry, const char *name, | 1451 | int (*inode_setxattr) (struct dentry *dentry, const char *name, |
1549 | const void *value, size_t size, int flags); | 1452 | const void *value, size_t size, int flags); |
1550 | void (*inode_post_setxattr) (struct dentry *dentry, const char *name, | 1453 | void (*inode_post_setxattr) (struct dentry *dentry, const char *name, |
@@ -1585,20 +1488,16 @@ struct security_operations { | |||
1585 | void (*cred_free) (struct cred *cred); | 1488 | void (*cred_free) (struct cred *cred); |
1586 | int (*cred_prepare)(struct cred *new, const struct cred *old, | 1489 | int (*cred_prepare)(struct cred *new, const struct cred *old, |
1587 | gfp_t gfp); | 1490 | gfp_t gfp); |
1588 | void (*cred_commit)(struct cred *new, const struct cred *old); | ||
1589 | void (*cred_transfer)(struct cred *new, const struct cred *old); | 1491 | void (*cred_transfer)(struct cred *new, const struct cred *old); |
1590 | int (*kernel_act_as)(struct cred *new, u32 secid); | 1492 | int (*kernel_act_as)(struct cred *new, u32 secid); |
1591 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); | 1493 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); |
1592 | int (*kernel_module_request)(char *kmod_name); | 1494 | int (*kernel_module_request)(char *kmod_name); |
1593 | int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags); | ||
1594 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, | 1495 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, |
1595 | int flags); | 1496 | int flags); |
1596 | int (*task_setgid) (gid_t id0, gid_t id1, gid_t id2, int flags); | ||
1597 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); | 1497 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); |
1598 | int (*task_getpgid) (struct task_struct *p); | 1498 | int (*task_getpgid) (struct task_struct *p); |
1599 | int (*task_getsid) (struct task_struct *p); | 1499 | int (*task_getsid) (struct task_struct *p); |
1600 | void (*task_getsecid) (struct task_struct *p, u32 *secid); | 1500 | void (*task_getsecid) (struct task_struct *p, u32 *secid); |
1601 | int (*task_setgroups) (struct group_info *group_info); | ||
1602 | int (*task_setnice) (struct task_struct *p, int nice); | 1501 | int (*task_setnice) (struct task_struct *p, int nice); |
1603 | int (*task_setioprio) (struct task_struct *p, int ioprio); | 1502 | int (*task_setioprio) (struct task_struct *p, int ioprio); |
1604 | int (*task_getioprio) (struct task_struct *p); | 1503 | int (*task_getioprio) (struct task_struct *p); |
@@ -1728,9 +1627,6 @@ struct security_operations { | |||
1728 | const struct cred *cred, | 1627 | const struct cred *cred, |
1729 | key_perm_t perm); | 1628 | key_perm_t perm); |
1730 | int (*key_getsecurity)(struct key *key, char **_buffer); | 1629 | int (*key_getsecurity)(struct key *key, char **_buffer); |
1731 | int (*key_session_to_parent)(const struct cred *cred, | ||
1732 | const struct cred *parent_cred, | ||
1733 | struct key *key); | ||
1734 | #endif /* CONFIG_KEYS */ | 1630 | #endif /* CONFIG_KEYS */ |
1735 | 1631 | ||
1736 | #ifdef CONFIG_AUDIT | 1632 | #ifdef CONFIG_AUDIT |
@@ -1761,7 +1657,6 @@ int security_capset(struct cred *new, const struct cred *old, | |||
1761 | int security_capable(int cap); | 1657 | int security_capable(int cap); |
1762 | int security_real_capable(struct task_struct *tsk, int cap); | 1658 | int security_real_capable(struct task_struct *tsk, int cap); |
1763 | int security_real_capable_noaudit(struct task_struct *tsk, int cap); | 1659 | int security_real_capable_noaudit(struct task_struct *tsk, int cap); |
1764 | int security_acct(struct file *file); | ||
1765 | int security_sysctl(struct ctl_table *table, int op); | 1660 | int security_sysctl(struct ctl_table *table, int op); |
1766 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); | 1661 | int security_quotactl(int cmds, int type, int id, struct super_block *sb); |
1767 | int security_quota_on(struct dentry *dentry); | 1662 | int security_quota_on(struct dentry *dentry); |
@@ -1783,14 +1678,8 @@ int security_sb_show_options(struct seq_file *m, struct super_block *sb); | |||
1783 | int security_sb_statfs(struct dentry *dentry); | 1678 | int security_sb_statfs(struct dentry *dentry); |
1784 | int security_sb_mount(char *dev_name, struct path *path, | 1679 | int security_sb_mount(char *dev_name, struct path *path, |
1785 | char *type, unsigned long flags, void *data); | 1680 | char *type, unsigned long flags, void *data); |
1786 | int security_sb_check_sb(struct vfsmount *mnt, struct path *path); | ||
1787 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1681 | int security_sb_umount(struct vfsmount *mnt, int flags); |
1788 | void security_sb_umount_close(struct vfsmount *mnt); | ||
1789 | void security_sb_umount_busy(struct vfsmount *mnt); | ||
1790 | void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data); | ||
1791 | void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint); | ||
1792 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1682 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
1793 | void security_sb_post_pivotroot(struct path *old_path, struct path *new_path); | ||
1794 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 1683 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); |
1795 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1684 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, |
1796 | struct super_block *newsb); | 1685 | struct super_block *newsb); |
@@ -1816,7 +1705,6 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); | |||
1816 | int security_inode_permission(struct inode *inode, int mask); | 1705 | int security_inode_permission(struct inode *inode, int mask); |
1817 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); | 1706 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); |
1818 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); | 1707 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); |
1819 | void security_inode_delete(struct inode *inode); | ||
1820 | int security_inode_setxattr(struct dentry *dentry, const char *name, | 1708 | int security_inode_setxattr(struct dentry *dentry, const char *name, |
1821 | const void *value, size_t size, int flags); | 1709 | const void *value, size_t size, int flags); |
1822 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, | 1710 | void security_inode_post_setxattr(struct dentry *dentry, const char *name, |
@@ -1850,20 +1738,16 @@ int security_task_create(unsigned long clone_flags); | |||
1850 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); | 1738 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); |
1851 | void security_cred_free(struct cred *cred); | 1739 | void security_cred_free(struct cred *cred); |
1852 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); | 1740 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); |
1853 | void security_commit_creds(struct cred *new, const struct cred *old); | ||
1854 | void security_transfer_creds(struct cred *new, const struct cred *old); | 1741 | void security_transfer_creds(struct cred *new, const struct cred *old); |
1855 | int security_kernel_act_as(struct cred *new, u32 secid); | 1742 | int security_kernel_act_as(struct cred *new, u32 secid); |
1856 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); | 1743 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); |
1857 | int security_kernel_module_request(char *kmod_name); | 1744 | int security_kernel_module_request(char *kmod_name); |
1858 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags); | ||
1859 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 1745 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
1860 | int flags); | 1746 | int flags); |
1861 | int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags); | ||
1862 | int security_task_setpgid(struct task_struct *p, pid_t pgid); | 1747 | int security_task_setpgid(struct task_struct *p, pid_t pgid); |
1863 | int security_task_getpgid(struct task_struct *p); | 1748 | int security_task_getpgid(struct task_struct *p); |
1864 | int security_task_getsid(struct task_struct *p); | 1749 | int security_task_getsid(struct task_struct *p); |
1865 | void security_task_getsecid(struct task_struct *p, u32 *secid); | 1750 | void security_task_getsecid(struct task_struct *p, u32 *secid); |
1866 | int security_task_setgroups(struct group_info *group_info); | ||
1867 | int security_task_setnice(struct task_struct *p, int nice); | 1751 | int security_task_setnice(struct task_struct *p, int nice); |
1868 | int security_task_setioprio(struct task_struct *p, int ioprio); | 1752 | int security_task_setioprio(struct task_struct *p, int ioprio); |
1869 | int security_task_getioprio(struct task_struct *p); | 1753 | int security_task_getioprio(struct task_struct *p); |
@@ -1990,11 +1874,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) | |||
1990 | return ret; | 1874 | return ret; |
1991 | } | 1875 | } |
1992 | 1876 | ||
1993 | static inline int security_acct(struct file *file) | ||
1994 | { | ||
1995 | return 0; | ||
1996 | } | ||
1997 | |||
1998 | static inline int security_sysctl(struct ctl_table *table, int op) | 1877 | static inline int security_sysctl(struct ctl_table *table, int op) |
1999 | { | 1878 | { |
2000 | return 0; | 1879 | return 0; |
@@ -2099,41 +1978,17 @@ static inline int security_sb_mount(char *dev_name, struct path *path, | |||
2099 | return 0; | 1978 | return 0; |
2100 | } | 1979 | } |
2101 | 1980 | ||
2102 | static inline int security_sb_check_sb(struct vfsmount *mnt, | ||
2103 | struct path *path) | ||
2104 | { | ||
2105 | return 0; | ||
2106 | } | ||
2107 | |||
2108 | static inline int security_sb_umount(struct vfsmount *mnt, int flags) | 1981 | static inline int security_sb_umount(struct vfsmount *mnt, int flags) |
2109 | { | 1982 | { |
2110 | return 0; | 1983 | return 0; |
2111 | } | 1984 | } |
2112 | 1985 | ||
2113 | static inline void security_sb_umount_close(struct vfsmount *mnt) | ||
2114 | { } | ||
2115 | |||
2116 | static inline void security_sb_umount_busy(struct vfsmount *mnt) | ||
2117 | { } | ||
2118 | |||
2119 | static inline void security_sb_post_remount(struct vfsmount *mnt, | ||
2120 | unsigned long flags, void *data) | ||
2121 | { } | ||
2122 | |||
2123 | static inline void security_sb_post_addmount(struct vfsmount *mnt, | ||
2124 | struct path *mountpoint) | ||
2125 | { } | ||
2126 | |||
2127 | static inline int security_sb_pivotroot(struct path *old_path, | 1986 | static inline int security_sb_pivotroot(struct path *old_path, |
2128 | struct path *new_path) | 1987 | struct path *new_path) |
2129 | { | 1988 | { |
2130 | return 0; | 1989 | return 0; |
2131 | } | 1990 | } |
2132 | 1991 | ||
2133 | static inline void security_sb_post_pivotroot(struct path *old_path, | ||
2134 | struct path *new_path) | ||
2135 | { } | ||
2136 | |||
2137 | static inline int security_sb_set_mnt_opts(struct super_block *sb, | 1992 | static inline int security_sb_set_mnt_opts(struct super_block *sb, |
2138 | struct security_mnt_opts *opts) | 1993 | struct security_mnt_opts *opts) |
2139 | { | 1994 | { |
@@ -2249,9 +2104,6 @@ static inline int security_inode_getattr(struct vfsmount *mnt, | |||
2249 | return 0; | 2104 | return 0; |
2250 | } | 2105 | } |
2251 | 2106 | ||
2252 | static inline void security_inode_delete(struct inode *inode) | ||
2253 | { } | ||
2254 | |||
2255 | static inline int security_inode_setxattr(struct dentry *dentry, | 2107 | static inline int security_inode_setxattr(struct dentry *dentry, |
2256 | const char *name, const void *value, size_t size, int flags) | 2108 | const char *name, const void *value, size_t size, int flags) |
2257 | { | 2109 | { |
@@ -2398,11 +2250,6 @@ static inline int security_prepare_creds(struct cred *new, | |||
2398 | return 0; | 2250 | return 0; |
2399 | } | 2251 | } |
2400 | 2252 | ||
2401 | static inline void security_commit_creds(struct cred *new, | ||
2402 | const struct cred *old) | ||
2403 | { | ||
2404 | } | ||
2405 | |||
2406 | static inline void security_transfer_creds(struct cred *new, | 2253 | static inline void security_transfer_creds(struct cred *new, |
2407 | const struct cred *old) | 2254 | const struct cred *old) |
2408 | { | 2255 | { |
@@ -2424,12 +2271,6 @@ static inline int security_kernel_module_request(char *kmod_name) | |||
2424 | return 0; | 2271 | return 0; |
2425 | } | 2272 | } |
2426 | 2273 | ||
2427 | static inline int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, | ||
2428 | int flags) | ||
2429 | { | ||
2430 | return 0; | ||
2431 | } | ||
2432 | |||
2433 | static inline int security_task_fix_setuid(struct cred *new, | 2274 | static inline int security_task_fix_setuid(struct cred *new, |
2434 | const struct cred *old, | 2275 | const struct cred *old, |
2435 | int flags) | 2276 | int flags) |
@@ -2437,12 +2278,6 @@ static inline int security_task_fix_setuid(struct cred *new, | |||
2437 | return cap_task_fix_setuid(new, old, flags); | 2278 | return cap_task_fix_setuid(new, old, flags); |
2438 | } | 2279 | } |
2439 | 2280 | ||
2440 | static inline int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, | ||
2441 | int flags) | ||
2442 | { | ||
2443 | return 0; | ||
2444 | } | ||
2445 | |||
2446 | static inline int security_task_setpgid(struct task_struct *p, pid_t pgid) | 2281 | static inline int security_task_setpgid(struct task_struct *p, pid_t pgid) |
2447 | { | 2282 | { |
2448 | return 0; | 2283 | return 0; |
@@ -2463,11 +2298,6 @@ static inline void security_task_getsecid(struct task_struct *p, u32 *secid) | |||
2463 | *secid = 0; | 2298 | *secid = 0; |
2464 | } | 2299 | } |
2465 | 2300 | ||
2466 | static inline int security_task_setgroups(struct group_info *group_info) | ||
2467 | { | ||
2468 | return 0; | ||
2469 | } | ||
2470 | |||
2471 | static inline int security_task_setnice(struct task_struct *p, int nice) | 2301 | static inline int security_task_setnice(struct task_struct *p, int nice) |
2472 | { | 2302 | { |
2473 | return cap_task_setnice(p, nice); | 2303 | return cap_task_setnice(p, nice); |
@@ -3064,9 +2894,6 @@ void security_key_free(struct key *key); | |||
3064 | int security_key_permission(key_ref_t key_ref, | 2894 | int security_key_permission(key_ref_t key_ref, |
3065 | const struct cred *cred, key_perm_t perm); | 2895 | const struct cred *cred, key_perm_t perm); |
3066 | int security_key_getsecurity(struct key *key, char **_buffer); | 2896 | int security_key_getsecurity(struct key *key, char **_buffer); |
3067 | int security_key_session_to_parent(const struct cred *cred, | ||
3068 | const struct cred *parent_cred, | ||
3069 | struct key *key); | ||
3070 | 2897 | ||
3071 | #else | 2898 | #else |
3072 | 2899 | ||
@@ -3094,13 +2921,6 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer) | |||
3094 | return 0; | 2921 | return 0; |
3095 | } | 2922 | } |
3096 | 2923 | ||
3097 | static inline int security_key_session_to_parent(const struct cred *cred, | ||
3098 | const struct cred *parent_cred, | ||
3099 | struct key *key) | ||
3100 | { | ||
3101 | return 0; | ||
3102 | } | ||
3103 | |||
3104 | #endif | 2924 | #endif |
3105 | #endif /* CONFIG_KEYS */ | 2925 | #endif /* CONFIG_KEYS */ |
3106 | 2926 | ||
diff --git a/kernel/acct.c b/kernel/acct.c index e4c0e1fee9b0..385b88461c29 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -216,7 +216,6 @@ static int acct_on(char *name) | |||
216 | { | 216 | { |
217 | struct file *file; | 217 | struct file *file; |
218 | struct vfsmount *mnt; | 218 | struct vfsmount *mnt; |
219 | int error; | ||
220 | struct pid_namespace *ns; | 219 | struct pid_namespace *ns; |
221 | struct bsd_acct_struct *acct = NULL; | 220 | struct bsd_acct_struct *acct = NULL; |
222 | 221 | ||
@@ -244,13 +243,6 @@ static int acct_on(char *name) | |||
244 | } | 243 | } |
245 | } | 244 | } |
246 | 245 | ||
247 | error = security_acct(file); | ||
248 | if (error) { | ||
249 | kfree(acct); | ||
250 | filp_close(file, NULL); | ||
251 | return error; | ||
252 | } | ||
253 | |||
254 | spin_lock(&acct_lock); | 246 | spin_lock(&acct_lock); |
255 | if (ns->bacct == NULL) { | 247 | if (ns->bacct == NULL) { |
256 | ns->bacct = acct; | 248 | ns->bacct = acct; |
@@ -281,7 +273,7 @@ static int acct_on(char *name) | |||
281 | */ | 273 | */ |
282 | SYSCALL_DEFINE1(acct, const char __user *, name) | 274 | SYSCALL_DEFINE1(acct, const char __user *, name) |
283 | { | 275 | { |
284 | int error; | 276 | int error = 0; |
285 | 277 | ||
286 | if (!capable(CAP_SYS_PACCT)) | 278 | if (!capable(CAP_SYS_PACCT)) |
287 | return -EPERM; | 279 | return -EPERM; |
@@ -299,13 +291,11 @@ SYSCALL_DEFINE1(acct, const char __user *, name) | |||
299 | if (acct == NULL) | 291 | if (acct == NULL) |
300 | return 0; | 292 | return 0; |
301 | 293 | ||
302 | error = security_acct(NULL); | 294 | spin_lock(&acct_lock); |
303 | if (!error) { | 295 | acct_file_reopen(acct, NULL, NULL); |
304 | spin_lock(&acct_lock); | 296 | spin_unlock(&acct_lock); |
305 | acct_file_reopen(acct, NULL, NULL); | ||
306 | spin_unlock(&acct_lock); | ||
307 | } | ||
308 | } | 297 | } |
298 | |||
309 | return error; | 299 | return error; |
310 | } | 300 | } |
311 | 301 | ||
diff --git a/kernel/cred.c b/kernel/cred.c index 62af1816c235..31f38a99adf7 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -523,8 +523,6 @@ int commit_creds(struct cred *new) | |||
523 | #endif | 523 | #endif |
524 | BUG_ON(atomic_read(&new->usage) < 1); | 524 | BUG_ON(atomic_read(&new->usage) < 1); |
525 | 525 | ||
526 | security_commit_creds(new, old); | ||
527 | |||
528 | get_cred(new); /* we will require a ref for the subj creds too */ | 526 | get_cred(new); /* we will require a ref for the subj creds too */ |
529 | 527 | ||
530 | /* dumpability changes */ | 528 | /* dumpability changes */ |
diff --git a/kernel/groups.c b/kernel/groups.c index 2b45b2ee3964..53b1916c9492 100644 --- a/kernel/groups.c +++ b/kernel/groups.c | |||
@@ -164,12 +164,6 @@ int groups_search(const struct group_info *group_info, gid_t grp) | |||
164 | */ | 164 | */ |
165 | int set_groups(struct cred *new, struct group_info *group_info) | 165 | int set_groups(struct cred *new, struct group_info *group_info) |
166 | { | 166 | { |
167 | int retval; | ||
168 | |||
169 | retval = security_task_setgroups(group_info); | ||
170 | if (retval) | ||
171 | return retval; | ||
172 | |||
173 | put_group_info(new->group_info); | 167 | put_group_info(new->group_info); |
174 | groups_sort(group_info); | 168 | groups_sort(group_info); |
175 | get_group_info(group_info); | 169 | get_group_info(group_info); |
diff --git a/kernel/sys.c b/kernel/sys.c index 7cb426a58965..0d36d889c74d 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -492,10 +492,6 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | |||
492 | return -ENOMEM; | 492 | return -ENOMEM; |
493 | old = current_cred(); | 493 | old = current_cred(); |
494 | 494 | ||
495 | retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE); | ||
496 | if (retval) | ||
497 | goto error; | ||
498 | |||
499 | retval = -EPERM; | 495 | retval = -EPERM; |
500 | if (rgid != (gid_t) -1) { | 496 | if (rgid != (gid_t) -1) { |
501 | if (old->gid == rgid || | 497 | if (old->gid == rgid || |
@@ -543,10 +539,6 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) | |||
543 | return -ENOMEM; | 539 | return -ENOMEM; |
544 | old = current_cred(); | 540 | old = current_cred(); |
545 | 541 | ||
546 | retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); | ||
547 | if (retval) | ||
548 | goto error; | ||
549 | |||
550 | retval = -EPERM; | 542 | retval = -EPERM; |
551 | if (capable(CAP_SETGID)) | 543 | if (capable(CAP_SETGID)) |
552 | new->gid = new->egid = new->sgid = new->fsgid = gid; | 544 | new->gid = new->egid = new->sgid = new->fsgid = gid; |
@@ -610,10 +602,6 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
610 | return -ENOMEM; | 602 | return -ENOMEM; |
611 | old = current_cred(); | 603 | old = current_cred(); |
612 | 604 | ||
613 | retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE); | ||
614 | if (retval) | ||
615 | goto error; | ||
616 | |||
617 | retval = -EPERM; | 605 | retval = -EPERM; |
618 | if (ruid != (uid_t) -1) { | 606 | if (ruid != (uid_t) -1) { |
619 | new->uid = ruid; | 607 | new->uid = ruid; |
@@ -675,10 +663,6 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
675 | return -ENOMEM; | 663 | return -ENOMEM; |
676 | old = current_cred(); | 664 | old = current_cred(); |
677 | 665 | ||
678 | retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID); | ||
679 | if (retval) | ||
680 | goto error; | ||
681 | |||
682 | retval = -EPERM; | 666 | retval = -EPERM; |
683 | if (capable(CAP_SETUID)) { | 667 | if (capable(CAP_SETUID)) { |
684 | new->suid = new->uid = uid; | 668 | new->suid = new->uid = uid; |
@@ -719,9 +703,6 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
719 | if (!new) | 703 | if (!new) |
720 | return -ENOMEM; | 704 | return -ENOMEM; |
721 | 705 | ||
722 | retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); | ||
723 | if (retval) | ||
724 | goto error; | ||
725 | old = current_cred(); | 706 | old = current_cred(); |
726 | 707 | ||
727 | retval = -EPERM; | 708 | retval = -EPERM; |
@@ -788,10 +769,6 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | |||
788 | return -ENOMEM; | 769 | return -ENOMEM; |
789 | old = current_cred(); | 770 | old = current_cred(); |
790 | 771 | ||
791 | retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); | ||
792 | if (retval) | ||
793 | goto error; | ||
794 | |||
795 | retval = -EPERM; | 772 | retval = -EPERM; |
796 | if (!capable(CAP_SETGID)) { | 773 | if (!capable(CAP_SETGID)) { |
797 | if (rgid != (gid_t) -1 && rgid != old->gid && | 774 | if (rgid != (gid_t) -1 && rgid != old->gid && |
@@ -851,9 +828,6 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) | |||
851 | old = current_cred(); | 828 | old = current_cred(); |
852 | old_fsuid = old->fsuid; | 829 | old_fsuid = old->fsuid; |
853 | 830 | ||
854 | if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0) | ||
855 | goto error; | ||
856 | |||
857 | if (uid == old->uid || uid == old->euid || | 831 | if (uid == old->uid || uid == old->euid || |
858 | uid == old->suid || uid == old->fsuid || | 832 | uid == old->suid || uid == old->fsuid || |
859 | capable(CAP_SETUID)) { | 833 | capable(CAP_SETUID)) { |
@@ -864,7 +838,6 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) | |||
864 | } | 838 | } |
865 | } | 839 | } |
866 | 840 | ||
867 | error: | ||
868 | abort_creds(new); | 841 | abort_creds(new); |
869 | return old_fsuid; | 842 | return old_fsuid; |
870 | 843 | ||
@@ -888,9 +861,6 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) | |||
888 | old = current_cred(); | 861 | old = current_cred(); |
889 | old_fsgid = old->fsgid; | 862 | old_fsgid = old->fsgid; |
890 | 863 | ||
891 | if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) | ||
892 | goto error; | ||
893 | |||
894 | if (gid == old->gid || gid == old->egid || | 864 | if (gid == old->gid || gid == old->egid || |
895 | gid == old->sgid || gid == old->fsgid || | 865 | gid == old->sgid || gid == old->fsgid || |
896 | capable(CAP_SETGID)) { | 866 | capable(CAP_SETGID)) { |
@@ -900,7 +870,6 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) | |||
900 | } | 870 | } |
901 | } | 871 | } |
902 | 872 | ||
903 | error: | ||
904 | abort_creds(new); | 873 | abort_creds(new); |
905 | return old_fsgid; | 874 | return old_fsgid; |
906 | 875 | ||
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index 24626968055d..58a12c278706 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c | |||
@@ -81,7 +81,7 @@ int main(int argc, char *argv[]) | |||
81 | fprintf(fout, "\n"); | 81 | fprintf(fout, "\n"); |
82 | 82 | ||
83 | for (i = 1; i < isids_len; i++) { | 83 | for (i = 1; i < isids_len; i++) { |
84 | char *s = initial_sid_to_string[i]; | 84 | const char *s = initial_sid_to_string[i]; |
85 | fprintf(fout, "#define SECINITSID_%s", s); | 85 | fprintf(fout, "#define SECINITSID_%s", s); |
86 | for (j = 0; j < max(1, 40 - strlen(s)); j++) | 86 | for (j = 0; j < max(1, 40 - strlen(s)); j++) |
87 | fprintf(fout, " "); | 87 | fprintf(fout, " "); |
diff --git a/security/capability.c b/security/capability.c index 4875142b858d..8168e3ecd5bf 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -12,11 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | 14 | ||
15 | static int cap_acct(struct file *file) | ||
16 | { | ||
17 | return 0; | ||
18 | } | ||
19 | |||
20 | static int cap_sysctl(ctl_table *table, int op) | 15 | static int cap_sysctl(ctl_table *table, int op) |
21 | { | 16 | { |
22 | return 0; | 17 | return 0; |
@@ -80,42 +75,16 @@ static int cap_sb_mount(char *dev_name, struct path *path, char *type, | |||
80 | return 0; | 75 | return 0; |
81 | } | 76 | } |
82 | 77 | ||
83 | static int cap_sb_check_sb(struct vfsmount *mnt, struct path *path) | ||
84 | { | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int cap_sb_umount(struct vfsmount *mnt, int flags) | 78 | static int cap_sb_umount(struct vfsmount *mnt, int flags) |
89 | { | 79 | { |
90 | return 0; | 80 | return 0; |
91 | } | 81 | } |
92 | 82 | ||
93 | static void cap_sb_umount_close(struct vfsmount *mnt) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | static void cap_sb_umount_busy(struct vfsmount *mnt) | ||
98 | { | ||
99 | } | ||
100 | |||
101 | static void cap_sb_post_remount(struct vfsmount *mnt, unsigned long flags, | ||
102 | void *data) | ||
103 | { | ||
104 | } | ||
105 | |||
106 | static void cap_sb_post_addmount(struct vfsmount *mnt, struct path *path) | ||
107 | { | ||
108 | } | ||
109 | |||
110 | static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) | 83 | static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) |
111 | { | 84 | { |
112 | return 0; | 85 | return 0; |
113 | } | 86 | } |
114 | 87 | ||
115 | static void cap_sb_post_pivotroot(struct path *old_path, struct path *new_path) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | static int cap_sb_set_mnt_opts(struct super_block *sb, | 88 | static int cap_sb_set_mnt_opts(struct super_block *sb, |
120 | struct security_mnt_opts *opts) | 89 | struct security_mnt_opts *opts) |
121 | { | 90 | { |
@@ -221,10 +190,6 @@ static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
221 | return 0; | 190 | return 0; |
222 | } | 191 | } |
223 | 192 | ||
224 | static void cap_inode_delete(struct inode *ino) | ||
225 | { | ||
226 | } | ||
227 | |||
228 | static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, | 193 | static void cap_inode_post_setxattr(struct dentry *dentry, const char *name, |
229 | const void *value, size_t size, int flags) | 194 | const void *value, size_t size, int flags) |
230 | { | 195 | { |
@@ -403,10 +368,6 @@ static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) | |||
403 | return 0; | 368 | return 0; |
404 | } | 369 | } |
405 | 370 | ||
406 | static void cap_cred_commit(struct cred *new, const struct cred *old) | ||
407 | { | ||
408 | } | ||
409 | |||
410 | static void cap_cred_transfer(struct cred *new, const struct cred *old) | 371 | static void cap_cred_transfer(struct cred *new, const struct cred *old) |
411 | { | 372 | { |
412 | } | 373 | } |
@@ -426,16 +387,6 @@ static int cap_kernel_module_request(char *kmod_name) | |||
426 | return 0; | 387 | return 0; |
427 | } | 388 | } |
428 | 389 | ||
429 | static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | ||
430 | { | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | ||
435 | { | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) | 390 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) |
440 | { | 391 | { |
441 | return 0; | 392 | return 0; |
@@ -456,11 +407,6 @@ static void cap_task_getsecid(struct task_struct *p, u32 *secid) | |||
456 | *secid = 0; | 407 | *secid = 0; |
457 | } | 408 | } |
458 | 409 | ||
459 | static int cap_task_setgroups(struct group_info *group_info) | ||
460 | { | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int cap_task_getioprio(struct task_struct *p) | 410 | static int cap_task_getioprio(struct task_struct *p) |
465 | { | 411 | { |
466 | return 0; | 412 | return 0; |
@@ -875,13 +821,6 @@ static int cap_key_getsecurity(struct key *key, char **_buffer) | |||
875 | return 0; | 821 | return 0; |
876 | } | 822 | } |
877 | 823 | ||
878 | static int cap_key_session_to_parent(const struct cred *cred, | ||
879 | const struct cred *parent_cred, | ||
880 | struct key *key) | ||
881 | { | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | #endif /* CONFIG_KEYS */ | 824 | #endif /* CONFIG_KEYS */ |
886 | 825 | ||
887 | #ifdef CONFIG_AUDIT | 826 | #ifdef CONFIG_AUDIT |
@@ -915,13 +854,12 @@ static void cap_audit_rule_free(void *lsmrule) | |||
915 | } \ | 854 | } \ |
916 | } while (0) | 855 | } while (0) |
917 | 856 | ||
918 | void security_fixup_ops(struct security_operations *ops) | 857 | void __init security_fixup_ops(struct security_operations *ops) |
919 | { | 858 | { |
920 | set_to_cap_if_null(ops, ptrace_access_check); | 859 | set_to_cap_if_null(ops, ptrace_access_check); |
921 | set_to_cap_if_null(ops, ptrace_traceme); | 860 | set_to_cap_if_null(ops, ptrace_traceme); |
922 | set_to_cap_if_null(ops, capget); | 861 | set_to_cap_if_null(ops, capget); |
923 | set_to_cap_if_null(ops, capset); | 862 | set_to_cap_if_null(ops, capset); |
924 | set_to_cap_if_null(ops, acct); | ||
925 | set_to_cap_if_null(ops, capable); | 863 | set_to_cap_if_null(ops, capable); |
926 | set_to_cap_if_null(ops, quotactl); | 864 | set_to_cap_if_null(ops, quotactl); |
927 | set_to_cap_if_null(ops, quota_on); | 865 | set_to_cap_if_null(ops, quota_on); |
@@ -941,14 +879,8 @@ void security_fixup_ops(struct security_operations *ops) | |||
941 | set_to_cap_if_null(ops, sb_show_options); | 879 | set_to_cap_if_null(ops, sb_show_options); |
942 | set_to_cap_if_null(ops, sb_statfs); | 880 | set_to_cap_if_null(ops, sb_statfs); |
943 | set_to_cap_if_null(ops, sb_mount); | 881 | set_to_cap_if_null(ops, sb_mount); |
944 | set_to_cap_if_null(ops, sb_check_sb); | ||
945 | set_to_cap_if_null(ops, sb_umount); | 882 | set_to_cap_if_null(ops, sb_umount); |
946 | set_to_cap_if_null(ops, sb_umount_close); | ||
947 | set_to_cap_if_null(ops, sb_umount_busy); | ||
948 | set_to_cap_if_null(ops, sb_post_remount); | ||
949 | set_to_cap_if_null(ops, sb_post_addmount); | ||
950 | set_to_cap_if_null(ops, sb_pivotroot); | 883 | set_to_cap_if_null(ops, sb_pivotroot); |
951 | set_to_cap_if_null(ops, sb_post_pivotroot); | ||
952 | set_to_cap_if_null(ops, sb_set_mnt_opts); | 884 | set_to_cap_if_null(ops, sb_set_mnt_opts); |
953 | set_to_cap_if_null(ops, sb_clone_mnt_opts); | 885 | set_to_cap_if_null(ops, sb_clone_mnt_opts); |
954 | set_to_cap_if_null(ops, sb_parse_opts_str); | 886 | set_to_cap_if_null(ops, sb_parse_opts_str); |
@@ -968,7 +900,6 @@ void security_fixup_ops(struct security_operations *ops) | |||
968 | set_to_cap_if_null(ops, inode_permission); | 900 | set_to_cap_if_null(ops, inode_permission); |
969 | set_to_cap_if_null(ops, inode_setattr); | 901 | set_to_cap_if_null(ops, inode_setattr); |
970 | set_to_cap_if_null(ops, inode_getattr); | 902 | set_to_cap_if_null(ops, inode_getattr); |
971 | set_to_cap_if_null(ops, inode_delete); | ||
972 | set_to_cap_if_null(ops, inode_setxattr); | 903 | set_to_cap_if_null(ops, inode_setxattr); |
973 | set_to_cap_if_null(ops, inode_post_setxattr); | 904 | set_to_cap_if_null(ops, inode_post_setxattr); |
974 | set_to_cap_if_null(ops, inode_getxattr); | 905 | set_to_cap_if_null(ops, inode_getxattr); |
@@ -1009,19 +940,15 @@ void security_fixup_ops(struct security_operations *ops) | |||
1009 | set_to_cap_if_null(ops, cred_alloc_blank); | 940 | set_to_cap_if_null(ops, cred_alloc_blank); |
1010 | set_to_cap_if_null(ops, cred_free); | 941 | set_to_cap_if_null(ops, cred_free); |
1011 | set_to_cap_if_null(ops, cred_prepare); | 942 | set_to_cap_if_null(ops, cred_prepare); |
1012 | set_to_cap_if_null(ops, cred_commit); | ||
1013 | set_to_cap_if_null(ops, cred_transfer); | 943 | set_to_cap_if_null(ops, cred_transfer); |
1014 | set_to_cap_if_null(ops, kernel_act_as); | 944 | set_to_cap_if_null(ops, kernel_act_as); |
1015 | set_to_cap_if_null(ops, kernel_create_files_as); | 945 | set_to_cap_if_null(ops, kernel_create_files_as); |
1016 | set_to_cap_if_null(ops, kernel_module_request); | 946 | set_to_cap_if_null(ops, kernel_module_request); |
1017 | set_to_cap_if_null(ops, task_setuid); | ||
1018 | set_to_cap_if_null(ops, task_fix_setuid); | 947 | set_to_cap_if_null(ops, task_fix_setuid); |
1019 | set_to_cap_if_null(ops, task_setgid); | ||
1020 | set_to_cap_if_null(ops, task_setpgid); | 948 | set_to_cap_if_null(ops, task_setpgid); |
1021 | set_to_cap_if_null(ops, task_getpgid); | 949 | set_to_cap_if_null(ops, task_getpgid); |
1022 | set_to_cap_if_null(ops, task_getsid); | 950 | set_to_cap_if_null(ops, task_getsid); |
1023 | set_to_cap_if_null(ops, task_getsecid); | 951 | set_to_cap_if_null(ops, task_getsecid); |
1024 | set_to_cap_if_null(ops, task_setgroups); | ||
1025 | set_to_cap_if_null(ops, task_setnice); | 952 | set_to_cap_if_null(ops, task_setnice); |
1026 | set_to_cap_if_null(ops, task_setioprio); | 953 | set_to_cap_if_null(ops, task_setioprio); |
1027 | set_to_cap_if_null(ops, task_getioprio); | 954 | set_to_cap_if_null(ops, task_getioprio); |
@@ -1113,7 +1040,6 @@ void security_fixup_ops(struct security_operations *ops) | |||
1113 | set_to_cap_if_null(ops, key_free); | 1040 | set_to_cap_if_null(ops, key_free); |
1114 | set_to_cap_if_null(ops, key_permission); | 1041 | set_to_cap_if_null(ops, key_permission); |
1115 | set_to_cap_if_null(ops, key_getsecurity); | 1042 | set_to_cap_if_null(ops, key_getsecurity); |
1116 | set_to_cap_if_null(ops, key_session_to_parent); | ||
1117 | #endif /* CONFIG_KEYS */ | 1043 | #endif /* CONFIG_KEYS */ |
1118 | #ifdef CONFIG_AUDIT | 1044 | #ifdef CONFIG_AUDIT |
1119 | set_to_cap_if_null(ops, audit_rule_init); | 1045 | set_to_cap_if_null(ops, audit_rule_init); |
diff --git a/security/commoncap.c b/security/commoncap.c index 61669730da98..4e015996dd4d 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -570,7 +570,7 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name, | |||
570 | } | 570 | } |
571 | 571 | ||
572 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 572 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
573 | sizeof(XATTR_SECURITY_PREFIX) - 1) && | 573 | sizeof(XATTR_SECURITY_PREFIX) - 1) && |
574 | !capable(CAP_SYS_ADMIN)) | 574 | !capable(CAP_SYS_ADMIN)) |
575 | return -EPERM; | 575 | return -EPERM; |
576 | return 0; | 576 | return 0; |
@@ -596,7 +596,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
596 | } | 596 | } |
597 | 597 | ||
598 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 598 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
599 | sizeof(XATTR_SECURITY_PREFIX) - 1) && | 599 | sizeof(XATTR_SECURITY_PREFIX) - 1) && |
600 | !capable(CAP_SYS_ADMIN)) | 600 | !capable(CAP_SYS_ADMIN)) |
601 | return -EPERM; | 601 | return -EPERM; |
602 | return 0; | 602 | return 0; |
@@ -931,7 +931,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) | |||
931 | * @addr: address attempting to be mapped | 931 | * @addr: address attempting to be mapped |
932 | * @addr_only: unused | 932 | * @addr_only: unused |
933 | * | 933 | * |
934 | * If the process is attempting to map memory below mmap_min_addr they need | 934 | * If the process is attempting to map memory below dac_mmap_min_addr they need |
935 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the | 935 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the |
936 | * capability security module. Returns 0 if this mapping should be allowed | 936 | * capability security module. Returns 0 if this mapping should be allowed |
937 | * -EPERM if not. | 937 | * -EPERM if not. |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index f77c60423992..8d9c48f13774 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -470,7 +470,7 @@ struct cgroup_subsys devices_subsys = { | |||
470 | .name = "devices", | 470 | .name = "devices", |
471 | .can_attach = devcgroup_can_attach, | 471 | .can_attach = devcgroup_can_attach, |
472 | .create = devcgroup_create, | 472 | .create = devcgroup_create, |
473 | .destroy = devcgroup_destroy, | 473 | .destroy = devcgroup_destroy, |
474 | .populate = devcgroup_populate, | 474 | .populate = devcgroup_populate, |
475 | .subsys_id = devices_subsys_id, | 475 | .subsys_id = devices_subsys_id, |
476 | }; | 476 | }; |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 3d7846de8069..b6ecfd4d8d78 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -2,15 +2,14 @@ | |||
2 | # | 2 | # |
3 | config IMA | 3 | config IMA |
4 | bool "Integrity Measurement Architecture(IMA)" | 4 | bool "Integrity Measurement Architecture(IMA)" |
5 | depends on ACPI | ||
6 | depends on SECURITY | 5 | depends on SECURITY |
7 | select SECURITYFS | 6 | select SECURITYFS |
8 | select CRYPTO | 7 | select CRYPTO |
9 | select CRYPTO_HMAC | 8 | select CRYPTO_HMAC |
10 | select CRYPTO_MD5 | 9 | select CRYPTO_MD5 |
11 | select CRYPTO_SHA1 | 10 | select CRYPTO_SHA1 |
12 | select TCG_TPM | 11 | select TCG_TPM if !S390 |
13 | select TCG_TIS | 12 | select TCG_TIS if TCG_TPM |
14 | help | 13 | help |
15 | The Trusted Computing Group(TCG) runtime Integrity | 14 | The Trusted Computing Group(TCG) runtime Integrity |
16 | Measurement Architecture(IMA) maintains a list of hash | 15 | Measurement Architecture(IMA) maintains a list of hash |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 47fb65d1fcbd..16d100d3fc38 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -135,7 +135,7 @@ enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; | |||
135 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); | 135 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); |
136 | void ima_init_policy(void); | 136 | void ima_init_policy(void); |
137 | void ima_update_policy(void); | 137 | void ima_update_policy(void); |
138 | int ima_parse_add_rule(char *); | 138 | ssize_t ima_parse_add_rule(char *); |
139 | void ima_delete_rules(void); | 139 | void ima_delete_rules(void); |
140 | 140 | ||
141 | /* LSM based policy rules require audit */ | 141 | /* LSM based policy rules require audit */ |
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index 5af76340470c..c5c5a72c30be 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c | |||
@@ -41,7 +41,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, | |||
41 | return; | 41 | return; |
42 | 42 | ||
43 | ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); | 43 | ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); |
44 | audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u", | 44 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", |
45 | current->pid, current_cred()->uid, | 45 | current->pid, current_cred()->uid, |
46 | audit_get_loginuid(current), | 46 | audit_get_loginuid(current), |
47 | audit_get_sessionid(current)); | 47 | audit_get_sessionid(current)); |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 952e51373f58..9b3ade7468b2 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -27,7 +27,7 @@ static int init_desc(struct hash_desc *desc) | |||
27 | 27 | ||
28 | desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); | 28 | desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); |
29 | if (IS_ERR(desc->tfm)) { | 29 | if (IS_ERR(desc->tfm)) { |
30 | pr_info("failed to load %s transform: %ld\n", | 30 | pr_info("IMA: failed to load %s transform: %ld\n", |
31 | ima_hash, PTR_ERR(desc->tfm)); | 31 | ima_hash, PTR_ERR(desc->tfm)); |
32 | rc = PTR_ERR(desc->tfm); | 32 | rc = PTR_ERR(desc->tfm); |
33 | return rc; | 33 | return rc; |
@@ -112,7 +112,7 @@ static void __init ima_pcrread(int idx, u8 *pcr) | |||
112 | return; | 112 | return; |
113 | 113 | ||
114 | if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) | 114 | if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) |
115 | pr_err("Error Communicating to TPM chip\n"); | 115 | pr_err("IMA: Error Communicating to TPM chip\n"); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 07cb9c338cc4..8fe736aabe71 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
@@ -244,32 +244,34 @@ static const struct file_operations ima_ascii_measurements_ops = { | |||
244 | static ssize_t ima_write_policy(struct file *file, const char __user *buf, | 244 | static ssize_t ima_write_policy(struct file *file, const char __user *buf, |
245 | size_t datalen, loff_t *ppos) | 245 | size_t datalen, loff_t *ppos) |
246 | { | 246 | { |
247 | char *data; | 247 | char *data = NULL; |
248 | int rc; | 248 | ssize_t result; |
249 | 249 | ||
250 | if (datalen >= PAGE_SIZE) | 250 | if (datalen >= PAGE_SIZE) |
251 | return -ENOMEM; | 251 | datalen = PAGE_SIZE - 1; |
252 | if (*ppos != 0) { | 252 | |
253 | /* No partial writes. */ | 253 | /* No partial writes. */ |
254 | return -EINVAL; | 254 | result = -EINVAL; |
255 | } | 255 | if (*ppos != 0) |
256 | goto out; | ||
257 | |||
258 | result = -ENOMEM; | ||
256 | data = kmalloc(datalen + 1, GFP_KERNEL); | 259 | data = kmalloc(datalen + 1, GFP_KERNEL); |
257 | if (!data) | 260 | if (!data) |
258 | return -ENOMEM; | 261 | goto out; |
259 | 262 | ||
260 | if (copy_from_user(data, buf, datalen)) { | ||
261 | kfree(data); | ||
262 | return -EFAULT; | ||
263 | } | ||
264 | *(data + datalen) = '\0'; | 263 | *(data + datalen) = '\0'; |
265 | rc = ima_parse_add_rule(data); | ||
266 | if (rc < 0) { | ||
267 | datalen = -EINVAL; | ||
268 | valid_policy = 0; | ||
269 | } | ||
270 | 264 | ||
265 | result = -EFAULT; | ||
266 | if (copy_from_user(data, buf, datalen)) | ||
267 | goto out; | ||
268 | |||
269 | result = ima_parse_add_rule(data); | ||
270 | out: | ||
271 | if (result < 0) | ||
272 | valid_policy = 0; | ||
271 | kfree(data); | 273 | kfree(data); |
272 | return datalen; | 274 | return result; |
273 | } | 275 | } |
274 | 276 | ||
275 | static struct dentry *ima_dir; | 277 | static struct dentry *ima_dir; |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 2c744d488014..2dc2d6594145 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -80,17 +80,17 @@ void iint_free(struct kref *kref) | |||
80 | iint->version = 0; | 80 | iint->version = 0; |
81 | iint->flags = 0UL; | 81 | iint->flags = 0UL; |
82 | if (iint->readcount != 0) { | 82 | if (iint->readcount != 0) { |
83 | printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__, | 83 | printk(KERN_INFO "%s: readcount: %ld\n", __func__, |
84 | iint->readcount); | 84 | iint->readcount); |
85 | iint->readcount = 0; | 85 | iint->readcount = 0; |
86 | } | 86 | } |
87 | if (iint->writecount != 0) { | 87 | if (iint->writecount != 0) { |
88 | printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__, | 88 | printk(KERN_INFO "%s: writecount: %ld\n", __func__, |
89 | iint->writecount); | 89 | iint->writecount); |
90 | iint->writecount = 0; | 90 | iint->writecount = 0; |
91 | } | 91 | } |
92 | if (iint->opencount != 0) { | 92 | if (iint->opencount != 0) { |
93 | printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__, | 93 | printk(KERN_INFO "%s: opencount: %ld\n", __func__, |
94 | iint->opencount); | 94 | iint->opencount); |
95 | iint->opencount = 0; | 95 | iint->opencount = 0; |
96 | } | 96 | } |
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b1bcb702a27c..17f1f060306f 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -83,7 +83,7 @@ int __init ima_init(void) | |||
83 | ima_used_chip = 1; | 83 | ima_used_chip = 1; |
84 | 84 | ||
85 | if (!ima_used_chip) | 85 | if (!ima_used_chip) |
86 | pr_info("No TPM chip found, activating TPM-bypass!\n"); | 86 | pr_info("IMA: No TPM chip found, activating TPM-bypass!\n"); |
87 | 87 | ||
88 | ima_add_boot_aggregate(); /* boot aggregate must be first entry */ | 88 | ima_add_boot_aggregate(); /* boot aggregate must be first entry */ |
89 | ima_init_policy(); | 89 | ima_init_policy(); |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b2c89d9de2a4..f93641382e9f 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -195,7 +195,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | |||
195 | (iint->writecount < 0)) && | 195 | (iint->writecount < 0)) && |
196 | !ima_limit_imbalance(file)) { | 196 | !ima_limit_imbalance(file)) { |
197 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", | 197 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", |
198 | __FUNCTION__, iint->readcount, iint->writecount, | 198 | __func__, iint->readcount, iint->writecount, |
199 | iint->opencount); | 199 | iint->opencount); |
200 | dump_stack(); | 200 | dump_stack(); |
201 | } | 201 | } |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8643a93c5963..aef8c0a923ab 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -246,6 +246,9 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, | |||
246 | { | 246 | { |
247 | int result; | 247 | int result; |
248 | 248 | ||
249 | if (entry->lsm[lsm_rule].rule) | ||
250 | return -EINVAL; | ||
251 | |||
249 | entry->lsm[lsm_rule].type = audit_type; | 252 | entry->lsm[lsm_rule].type = audit_type; |
250 | result = security_filter_rule_init(entry->lsm[lsm_rule].type, | 253 | result = security_filter_rule_init(entry->lsm[lsm_rule].type, |
251 | Audit_equal, args, | 254 | Audit_equal, args, |
@@ -253,6 +256,13 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, | |||
253 | return result; | 256 | return result; |
254 | } | 257 | } |
255 | 258 | ||
259 | static void ima_log_string(struct audit_buffer *ab, char *key, char *value) | ||
260 | { | ||
261 | audit_log_format(ab, "%s=", key); | ||
262 | audit_log_untrustedstring(ab, value); | ||
263 | audit_log_format(ab, " "); | ||
264 | } | ||
265 | |||
256 | static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | 266 | static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) |
257 | { | 267 | { |
258 | struct audit_buffer *ab; | 268 | struct audit_buffer *ab; |
@@ -261,28 +271,41 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
261 | 271 | ||
262 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); | 272 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); |
263 | 273 | ||
264 | entry->action = -1; | 274 | entry->uid = -1; |
265 | while ((p = strsep(&rule, " \n")) != NULL) { | 275 | entry->action = UNKNOWN; |
276 | while ((p = strsep(&rule, " \t")) != NULL) { | ||
266 | substring_t args[MAX_OPT_ARGS]; | 277 | substring_t args[MAX_OPT_ARGS]; |
267 | int token; | 278 | int token; |
268 | unsigned long lnum; | 279 | unsigned long lnum; |
269 | 280 | ||
270 | if (result < 0) | 281 | if (result < 0) |
271 | break; | 282 | break; |
272 | if (!*p) | 283 | if ((*p == '\0') || (*p == ' ') || (*p == '\t')) |
273 | continue; | 284 | continue; |
274 | token = match_token(p, policy_tokens, args); | 285 | token = match_token(p, policy_tokens, args); |
275 | switch (token) { | 286 | switch (token) { |
276 | case Opt_measure: | 287 | case Opt_measure: |
277 | audit_log_format(ab, "%s ", "measure"); | 288 | ima_log_string(ab, "action", "measure"); |
289 | |||
290 | if (entry->action != UNKNOWN) | ||
291 | result = -EINVAL; | ||
292 | |||
278 | entry->action = MEASURE; | 293 | entry->action = MEASURE; |
279 | break; | 294 | break; |
280 | case Opt_dont_measure: | 295 | case Opt_dont_measure: |
281 | audit_log_format(ab, "%s ", "dont_measure"); | 296 | ima_log_string(ab, "action", "dont_measure"); |
297 | |||
298 | if (entry->action != UNKNOWN) | ||
299 | result = -EINVAL; | ||
300 | |||
282 | entry->action = DONT_MEASURE; | 301 | entry->action = DONT_MEASURE; |
283 | break; | 302 | break; |
284 | case Opt_func: | 303 | case Opt_func: |
285 | audit_log_format(ab, "func=%s ", args[0].from); | 304 | ima_log_string(ab, "func", args[0].from); |
305 | |||
306 | if (entry->func) | ||
307 | result = -EINVAL; | ||
308 | |||
286 | if (strcmp(args[0].from, "FILE_CHECK") == 0) | 309 | if (strcmp(args[0].from, "FILE_CHECK") == 0) |
287 | entry->func = FILE_CHECK; | 310 | entry->func = FILE_CHECK; |
288 | /* PATH_CHECK is for backwards compat */ | 311 | /* PATH_CHECK is for backwards compat */ |
@@ -298,7 +321,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
298 | entry->flags |= IMA_FUNC; | 321 | entry->flags |= IMA_FUNC; |
299 | break; | 322 | break; |
300 | case Opt_mask: | 323 | case Opt_mask: |
301 | audit_log_format(ab, "mask=%s ", args[0].from); | 324 | ima_log_string(ab, "mask", args[0].from); |
325 | |||
326 | if (entry->mask) | ||
327 | result = -EINVAL; | ||
328 | |||
302 | if ((strcmp(args[0].from, "MAY_EXEC")) == 0) | 329 | if ((strcmp(args[0].from, "MAY_EXEC")) == 0) |
303 | entry->mask = MAY_EXEC; | 330 | entry->mask = MAY_EXEC; |
304 | else if (strcmp(args[0].from, "MAY_WRITE") == 0) | 331 | else if (strcmp(args[0].from, "MAY_WRITE") == 0) |
@@ -313,14 +340,26 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
313 | entry->flags |= IMA_MASK; | 340 | entry->flags |= IMA_MASK; |
314 | break; | 341 | break; |
315 | case Opt_fsmagic: | 342 | case Opt_fsmagic: |
316 | audit_log_format(ab, "fsmagic=%s ", args[0].from); | 343 | ima_log_string(ab, "fsmagic", args[0].from); |
344 | |||
345 | if (entry->fsmagic) { | ||
346 | result = -EINVAL; | ||
347 | break; | ||
348 | } | ||
349 | |||
317 | result = strict_strtoul(args[0].from, 16, | 350 | result = strict_strtoul(args[0].from, 16, |
318 | &entry->fsmagic); | 351 | &entry->fsmagic); |
319 | if (!result) | 352 | if (!result) |
320 | entry->flags |= IMA_FSMAGIC; | 353 | entry->flags |= IMA_FSMAGIC; |
321 | break; | 354 | break; |
322 | case Opt_uid: | 355 | case Opt_uid: |
323 | audit_log_format(ab, "uid=%s ", args[0].from); | 356 | ima_log_string(ab, "uid", args[0].from); |
357 | |||
358 | if (entry->uid != -1) { | ||
359 | result = -EINVAL; | ||
360 | break; | ||
361 | } | ||
362 | |||
324 | result = strict_strtoul(args[0].from, 10, &lnum); | 363 | result = strict_strtoul(args[0].from, 10, &lnum); |
325 | if (!result) { | 364 | if (!result) { |
326 | entry->uid = (uid_t) lnum; | 365 | entry->uid = (uid_t) lnum; |
@@ -331,50 +370,51 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
331 | } | 370 | } |
332 | break; | 371 | break; |
333 | case Opt_obj_user: | 372 | case Opt_obj_user: |
334 | audit_log_format(ab, "obj_user=%s ", args[0].from); | 373 | ima_log_string(ab, "obj_user", args[0].from); |
335 | result = ima_lsm_rule_init(entry, args[0].from, | 374 | result = ima_lsm_rule_init(entry, args[0].from, |
336 | LSM_OBJ_USER, | 375 | LSM_OBJ_USER, |
337 | AUDIT_OBJ_USER); | 376 | AUDIT_OBJ_USER); |
338 | break; | 377 | break; |
339 | case Opt_obj_role: | 378 | case Opt_obj_role: |
340 | audit_log_format(ab, "obj_role=%s ", args[0].from); | 379 | ima_log_string(ab, "obj_role", args[0].from); |
341 | result = ima_lsm_rule_init(entry, args[0].from, | 380 | result = ima_lsm_rule_init(entry, args[0].from, |
342 | LSM_OBJ_ROLE, | 381 | LSM_OBJ_ROLE, |
343 | AUDIT_OBJ_ROLE); | 382 | AUDIT_OBJ_ROLE); |
344 | break; | 383 | break; |
345 | case Opt_obj_type: | 384 | case Opt_obj_type: |
346 | audit_log_format(ab, "obj_type=%s ", args[0].from); | 385 | ima_log_string(ab, "obj_type", args[0].from); |
347 | result = ima_lsm_rule_init(entry, args[0].from, | 386 | result = ima_lsm_rule_init(entry, args[0].from, |
348 | LSM_OBJ_TYPE, | 387 | LSM_OBJ_TYPE, |
349 | AUDIT_OBJ_TYPE); | 388 | AUDIT_OBJ_TYPE); |
350 | break; | 389 | break; |
351 | case Opt_subj_user: | 390 | case Opt_subj_user: |
352 | audit_log_format(ab, "subj_user=%s ", args[0].from); | 391 | ima_log_string(ab, "subj_user", args[0].from); |
353 | result = ima_lsm_rule_init(entry, args[0].from, | 392 | result = ima_lsm_rule_init(entry, args[0].from, |
354 | LSM_SUBJ_USER, | 393 | LSM_SUBJ_USER, |
355 | AUDIT_SUBJ_USER); | 394 | AUDIT_SUBJ_USER); |
356 | break; | 395 | break; |
357 | case Opt_subj_role: | 396 | case Opt_subj_role: |
358 | audit_log_format(ab, "subj_role=%s ", args[0].from); | 397 | ima_log_string(ab, "subj_role", args[0].from); |
359 | result = ima_lsm_rule_init(entry, args[0].from, | 398 | result = ima_lsm_rule_init(entry, args[0].from, |
360 | LSM_SUBJ_ROLE, | 399 | LSM_SUBJ_ROLE, |
361 | AUDIT_SUBJ_ROLE); | 400 | AUDIT_SUBJ_ROLE); |
362 | break; | 401 | break; |
363 | case Opt_subj_type: | 402 | case Opt_subj_type: |
364 | audit_log_format(ab, "subj_type=%s ", args[0].from); | 403 | ima_log_string(ab, "subj_type", args[0].from); |
365 | result = ima_lsm_rule_init(entry, args[0].from, | 404 | result = ima_lsm_rule_init(entry, args[0].from, |
366 | LSM_SUBJ_TYPE, | 405 | LSM_SUBJ_TYPE, |
367 | AUDIT_SUBJ_TYPE); | 406 | AUDIT_SUBJ_TYPE); |
368 | break; | 407 | break; |
369 | case Opt_err: | 408 | case Opt_err: |
370 | audit_log_format(ab, "UNKNOWN=%s ", p); | 409 | ima_log_string(ab, "UNKNOWN", p); |
410 | result = -EINVAL; | ||
371 | break; | 411 | break; |
372 | } | 412 | } |
373 | } | 413 | } |
374 | if (entry->action == UNKNOWN) | 414 | if (!result && (entry->action == UNKNOWN)) |
375 | result = -EINVAL; | 415 | result = -EINVAL; |
376 | 416 | ||
377 | audit_log_format(ab, "res=%d", !result ? 0 : 1); | 417 | audit_log_format(ab, "res=%d", !!result); |
378 | audit_log_end(ab); | 418 | audit_log_end(ab); |
379 | return result; | 419 | return result; |
380 | } | 420 | } |
@@ -384,13 +424,14 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
384 | * @rule - ima measurement policy rule | 424 | * @rule - ima measurement policy rule |
385 | * | 425 | * |
386 | * Uses a mutex to protect the policy list from multiple concurrent writers. | 426 | * Uses a mutex to protect the policy list from multiple concurrent writers. |
387 | * Returns 0 on success, an error code on failure. | 427 | * Returns the length of the rule parsed, an error code on failure |
388 | */ | 428 | */ |
389 | int ima_parse_add_rule(char *rule) | 429 | ssize_t ima_parse_add_rule(char *rule) |
390 | { | 430 | { |
391 | const char *op = "update_policy"; | 431 | const char *op = "update_policy"; |
432 | char *p; | ||
392 | struct ima_measure_rule_entry *entry; | 433 | struct ima_measure_rule_entry *entry; |
393 | int result = 0; | 434 | ssize_t result, len; |
394 | int audit_info = 0; | 435 | int audit_info = 0; |
395 | 436 | ||
396 | /* Prevent installed policy from changing */ | 437 | /* Prevent installed policy from changing */ |
@@ -410,18 +451,28 @@ int ima_parse_add_rule(char *rule) | |||
410 | 451 | ||
411 | INIT_LIST_HEAD(&entry->list); | 452 | INIT_LIST_HEAD(&entry->list); |
412 | 453 | ||
413 | result = ima_parse_rule(rule, entry); | 454 | p = strsep(&rule, "\n"); |
414 | if (!result) { | 455 | len = strlen(p) + 1; |
415 | mutex_lock(&ima_measure_mutex); | 456 | |
416 | list_add_tail(&entry->list, &measure_policy_rules); | 457 | if (*p == '#') { |
417 | mutex_unlock(&ima_measure_mutex); | 458 | kfree(entry); |
418 | } else { | 459 | return len; |
460 | } | ||
461 | |||
462 | result = ima_parse_rule(p, entry); | ||
463 | if (result) { | ||
419 | kfree(entry); | 464 | kfree(entry); |
420 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, | 465 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, |
421 | NULL, op, "invalid policy", result, | 466 | NULL, op, "invalid policy", result, |
422 | audit_info); | 467 | audit_info); |
468 | return result; | ||
423 | } | 469 | } |
424 | return result; | 470 | |
471 | mutex_lock(&ima_measure_mutex); | ||
472 | list_add_tail(&entry->list, &measure_policy_rules); | ||
473 | mutex_unlock(&ima_measure_mutex); | ||
474 | |||
475 | return len; | ||
425 | } | 476 | } |
426 | 477 | ||
427 | /* ima_delete_rules called to cleanup invalid policy */ | 478 | /* ima_delete_rules called to cleanup invalid policy */ |
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 46ba62b1adf5..8e28f04a5e2e 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c | |||
@@ -71,7 +71,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry) | |||
71 | 71 | ||
72 | qe = kmalloc(sizeof(*qe), GFP_KERNEL); | 72 | qe = kmalloc(sizeof(*qe), GFP_KERNEL); |
73 | if (qe == NULL) { | 73 | if (qe == NULL) { |
74 | pr_err("OUT OF MEMORY ERROR creating queue entry.\n"); | 74 | pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n"); |
75 | return -ENOMEM; | 75 | return -ENOMEM; |
76 | } | 76 | } |
77 | qe->entry = entry; | 77 | qe->entry = entry; |
@@ -94,7 +94,7 @@ static int ima_pcr_extend(const u8 *hash) | |||
94 | 94 | ||
95 | result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); | 95 | result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); |
96 | if (result != 0) | 96 | if (result != 0) |
97 | pr_err("Error Communicating to TPM chip\n"); | 97 | pr_err("IMA: Error Communicating to TPM chip\n"); |
98 | return result; | 98 | return result; |
99 | } | 99 | } |
100 | 100 | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index 24ba0307b7ad..5d4402a1161a 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -87,7 +87,16 @@ extern wait_queue_head_t request_key_conswq; | |||
87 | extern struct key_type *key_type_lookup(const char *type); | 87 | extern struct key_type *key_type_lookup(const char *type); |
88 | extern void key_type_put(struct key_type *ktype); | 88 | extern void key_type_put(struct key_type *ktype); |
89 | 89 | ||
90 | extern int __key_link(struct key *keyring, struct key *key); | 90 | extern int __key_link_begin(struct key *keyring, |
91 | const struct key_type *type, | ||
92 | const char *description, | ||
93 | struct keyring_list **_prealloc); | ||
94 | extern int __key_link_check_live_key(struct key *keyring, struct key *key); | ||
95 | extern void __key_link(struct key *keyring, struct key *key, | ||
96 | struct keyring_list **_prealloc); | ||
97 | extern void __key_link_end(struct key *keyring, | ||
98 | struct key_type *type, | ||
99 | struct keyring_list *prealloc); | ||
91 | 100 | ||
92 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 101 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
93 | const struct key_type *type, | 102 | const struct key_type *type, |
diff --git a/security/keys/key.c b/security/keys/key.c index e50d264c9ad1..c1eac8084ade 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -355,7 +355,7 @@ EXPORT_SYMBOL(key_alloc); | |||
355 | */ | 355 | */ |
356 | int key_payload_reserve(struct key *key, size_t datalen) | 356 | int key_payload_reserve(struct key *key, size_t datalen) |
357 | { | 357 | { |
358 | int delta = (int) datalen - key->datalen; | 358 | int delta = (int)datalen - key->datalen; |
359 | int ret = 0; | 359 | int ret = 0; |
360 | 360 | ||
361 | key_check(key); | 361 | key_check(key); |
@@ -398,7 +398,8 @@ static int __key_instantiate_and_link(struct key *key, | |||
398 | const void *data, | 398 | const void *data, |
399 | size_t datalen, | 399 | size_t datalen, |
400 | struct key *keyring, | 400 | struct key *keyring, |
401 | struct key *authkey) | 401 | struct key *authkey, |
402 | struct keyring_list **_prealloc) | ||
402 | { | 403 | { |
403 | int ret, awaken; | 404 | int ret, awaken; |
404 | 405 | ||
@@ -425,7 +426,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
425 | 426 | ||
426 | /* and link it into the destination keyring */ | 427 | /* and link it into the destination keyring */ |
427 | if (keyring) | 428 | if (keyring) |
428 | ret = __key_link(keyring, key); | 429 | __key_link(keyring, key, _prealloc); |
429 | 430 | ||
430 | /* disable the authorisation key */ | 431 | /* disable the authorisation key */ |
431 | if (authkey) | 432 | if (authkey) |
@@ -453,15 +454,21 @@ int key_instantiate_and_link(struct key *key, | |||
453 | struct key *keyring, | 454 | struct key *keyring, |
454 | struct key *authkey) | 455 | struct key *authkey) |
455 | { | 456 | { |
457 | struct keyring_list *prealloc; | ||
456 | int ret; | 458 | int ret; |
457 | 459 | ||
458 | if (keyring) | 460 | if (keyring) { |
459 | down_write(&keyring->sem); | 461 | ret = __key_link_begin(keyring, key->type, key->description, |
462 | &prealloc); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | } | ||
460 | 466 | ||
461 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); | 467 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, |
468 | &prealloc); | ||
462 | 469 | ||
463 | if (keyring) | 470 | if (keyring) |
464 | up_write(&keyring->sem); | 471 | __key_link_end(keyring, key->type, prealloc); |
465 | 472 | ||
466 | return ret; | 473 | return ret; |
467 | 474 | ||
@@ -478,8 +485,9 @@ int key_negate_and_link(struct key *key, | |||
478 | struct key *keyring, | 485 | struct key *keyring, |
479 | struct key *authkey) | 486 | struct key *authkey) |
480 | { | 487 | { |
488 | struct keyring_list *prealloc; | ||
481 | struct timespec now; | 489 | struct timespec now; |
482 | int ret, awaken; | 490 | int ret, awaken, link_ret = 0; |
483 | 491 | ||
484 | key_check(key); | 492 | key_check(key); |
485 | key_check(keyring); | 493 | key_check(keyring); |
@@ -488,7 +496,8 @@ int key_negate_and_link(struct key *key, | |||
488 | ret = -EBUSY; | 496 | ret = -EBUSY; |
489 | 497 | ||
490 | if (keyring) | 498 | if (keyring) |
491 | down_write(&keyring->sem); | 499 | link_ret = __key_link_begin(keyring, key->type, |
500 | key->description, &prealloc); | ||
492 | 501 | ||
493 | mutex_lock(&key_construction_mutex); | 502 | mutex_lock(&key_construction_mutex); |
494 | 503 | ||
@@ -508,8 +517,8 @@ int key_negate_and_link(struct key *key, | |||
508 | ret = 0; | 517 | ret = 0; |
509 | 518 | ||
510 | /* and link it into the destination keyring */ | 519 | /* and link it into the destination keyring */ |
511 | if (keyring) | 520 | if (keyring && link_ret == 0) |
512 | ret = __key_link(keyring, key); | 521 | __key_link(keyring, key, &prealloc); |
513 | 522 | ||
514 | /* disable the authorisation key */ | 523 | /* disable the authorisation key */ |
515 | if (authkey) | 524 | if (authkey) |
@@ -519,13 +528,13 @@ int key_negate_and_link(struct key *key, | |||
519 | mutex_unlock(&key_construction_mutex); | 528 | mutex_unlock(&key_construction_mutex); |
520 | 529 | ||
521 | if (keyring) | 530 | if (keyring) |
522 | up_write(&keyring->sem); | 531 | __key_link_end(keyring, key->type, prealloc); |
523 | 532 | ||
524 | /* wake up anyone waiting for a key to be constructed */ | 533 | /* wake up anyone waiting for a key to be constructed */ |
525 | if (awaken) | 534 | if (awaken) |
526 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); | 535 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
527 | 536 | ||
528 | return ret; | 537 | return ret == 0 ? link_ret : ret; |
529 | 538 | ||
530 | } /* end key_negate_and_link() */ | 539 | } /* end key_negate_and_link() */ |
531 | 540 | ||
@@ -749,6 +758,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
749 | key_perm_t perm, | 758 | key_perm_t perm, |
750 | unsigned long flags) | 759 | unsigned long flags) |
751 | { | 760 | { |
761 | struct keyring_list *prealloc; | ||
752 | const struct cred *cred = current_cred(); | 762 | const struct cred *cred = current_cred(); |
753 | struct key_type *ktype; | 763 | struct key_type *ktype; |
754 | struct key *keyring, *key = NULL; | 764 | struct key *keyring, *key = NULL; |
@@ -775,7 +785,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
775 | if (keyring->type != &key_type_keyring) | 785 | if (keyring->type != &key_type_keyring) |
776 | goto error_2; | 786 | goto error_2; |
777 | 787 | ||
778 | down_write(&keyring->sem); | 788 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
789 | if (ret < 0) | ||
790 | goto error_2; | ||
779 | 791 | ||
780 | /* if we're going to allocate a new key, we're going to have | 792 | /* if we're going to allocate a new key, we're going to have |
781 | * to modify the keyring */ | 793 | * to modify the keyring */ |
@@ -817,7 +829,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
817 | } | 829 | } |
818 | 830 | ||
819 | /* instantiate it and link it into the target keyring */ | 831 | /* instantiate it and link it into the target keyring */ |
820 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); | 832 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, |
833 | &prealloc); | ||
821 | if (ret < 0) { | 834 | if (ret < 0) { |
822 | key_put(key); | 835 | key_put(key); |
823 | key_ref = ERR_PTR(ret); | 836 | key_ref = ERR_PTR(ret); |
@@ -827,7 +840,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
827 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 840 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
828 | 841 | ||
829 | error_3: | 842 | error_3: |
830 | up_write(&keyring->sem); | 843 | __key_link_end(keyring, ktype, prealloc); |
831 | error_2: | 844 | error_2: |
832 | key_type_put(ktype); | 845 | key_type_put(ktype); |
833 | error: | 846 | error: |
@@ -837,7 +850,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
837 | /* we found a matching key, so we're going to try to update it | 850 | /* we found a matching key, so we're going to try to update it |
838 | * - we can drop the locks first as we have the key pinned | 851 | * - we can drop the locks first as we have the key pinned |
839 | */ | 852 | */ |
840 | up_write(&keyring->sem); | 853 | __key_link_end(keyring, ktype, prealloc); |
841 | key_type_put(ktype); | 854 | key_type_put(ktype); |
842 | 855 | ||
843 | key_ref = __key_update(key_ref, payload, plen); | 856 | key_ref = __key_update(key_ref, payload, plen); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index e9c2e7c584d9..8f4dce1987c4 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -212,15 +212,15 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
212 | ret = key->serial; | 212 | ret = key->serial; |
213 | 213 | ||
214 | key_put(key); | 214 | key_put(key); |
215 | error5: | 215 | error5: |
216 | key_type_put(ktype); | 216 | key_type_put(ktype); |
217 | error4: | 217 | error4: |
218 | key_ref_put(dest_ref); | 218 | key_ref_put(dest_ref); |
219 | error3: | 219 | error3: |
220 | kfree(callout_info); | 220 | kfree(callout_info); |
221 | error2: | 221 | error2: |
222 | kfree(description); | 222 | kfree(description); |
223 | error: | 223 | error: |
224 | return ret; | 224 | return ret; |
225 | 225 | ||
226 | } /* end sys_request_key() */ | 226 | } /* end sys_request_key() */ |
@@ -246,7 +246,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
246 | 246 | ||
247 | ret = key_ref_to_ptr(key_ref)->serial; | 247 | ret = key_ref_to_ptr(key_ref)->serial; |
248 | key_ref_put(key_ref); | 248 | key_ref_put(key_ref); |
249 | error: | 249 | error: |
250 | return ret; | 250 | return ret; |
251 | 251 | ||
252 | } /* end keyctl_get_keyring_ID() */ | 252 | } /* end keyctl_get_keyring_ID() */ |
@@ -275,7 +275,7 @@ long keyctl_join_session_keyring(const char __user *_name) | |||
275 | ret = join_session_keyring(name); | 275 | ret = join_session_keyring(name); |
276 | kfree(name); | 276 | kfree(name); |
277 | 277 | ||
278 | error: | 278 | error: |
279 | return ret; | 279 | return ret; |
280 | 280 | ||
281 | } /* end keyctl_join_session_keyring() */ | 281 | } /* end keyctl_join_session_keyring() */ |
@@ -322,9 +322,9 @@ long keyctl_update_key(key_serial_t id, | |||
322 | ret = key_update(key_ref, payload, plen); | 322 | ret = key_update(key_ref, payload, plen); |
323 | 323 | ||
324 | key_ref_put(key_ref); | 324 | key_ref_put(key_ref); |
325 | error2: | 325 | error2: |
326 | kfree(payload); | 326 | kfree(payload); |
327 | error: | 327 | error: |
328 | return ret; | 328 | return ret; |
329 | 329 | ||
330 | } /* end keyctl_update_key() */ | 330 | } /* end keyctl_update_key() */ |
@@ -356,7 +356,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
356 | ret = 0; | 356 | ret = 0; |
357 | 357 | ||
358 | key_ref_put(key_ref); | 358 | key_ref_put(key_ref); |
359 | error: | 359 | error: |
360 | return ret; | 360 | return ret; |
361 | 361 | ||
362 | } /* end keyctl_revoke_key() */ | 362 | } /* end keyctl_revoke_key() */ |
@@ -381,7 +381,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
381 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); | 381 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); |
382 | 382 | ||
383 | key_ref_put(keyring_ref); | 383 | key_ref_put(keyring_ref); |
384 | error: | 384 | error: |
385 | return ret; | 385 | return ret; |
386 | 386 | ||
387 | } /* end keyctl_keyring_clear() */ | 387 | } /* end keyctl_keyring_clear() */ |
@@ -413,9 +413,9 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
413 | ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); | 413 | ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); |
414 | 414 | ||
415 | key_ref_put(key_ref); | 415 | key_ref_put(key_ref); |
416 | error2: | 416 | error2: |
417 | key_ref_put(keyring_ref); | 417 | key_ref_put(keyring_ref); |
418 | error: | 418 | error: |
419 | return ret; | 419 | return ret; |
420 | 420 | ||
421 | } /* end keyctl_keyring_link() */ | 421 | } /* end keyctl_keyring_link() */ |
@@ -447,9 +447,9 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
447 | ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); | 447 | ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); |
448 | 448 | ||
449 | key_ref_put(key_ref); | 449 | key_ref_put(key_ref); |
450 | error2: | 450 | error2: |
451 | key_ref_put(keyring_ref); | 451 | key_ref_put(keyring_ref); |
452 | error: | 452 | error: |
453 | return ret; | 453 | return ret; |
454 | 454 | ||
455 | } /* end keyctl_keyring_unlink() */ | 455 | } /* end keyctl_keyring_unlink() */ |
@@ -529,9 +529,9 @@ okay: | |||
529 | } | 529 | } |
530 | 530 | ||
531 | kfree(tmpbuf); | 531 | kfree(tmpbuf); |
532 | error2: | 532 | error2: |
533 | key_ref_put(key_ref); | 533 | key_ref_put(key_ref); |
534 | error: | 534 | error: |
535 | return ret; | 535 | return ret; |
536 | 536 | ||
537 | } /* end keyctl_describe_key() */ | 537 | } /* end keyctl_describe_key() */ |
@@ -616,17 +616,17 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
616 | 616 | ||
617 | ret = key_ref_to_ptr(key_ref)->serial; | 617 | ret = key_ref_to_ptr(key_ref)->serial; |
618 | 618 | ||
619 | error6: | 619 | error6: |
620 | key_ref_put(key_ref); | 620 | key_ref_put(key_ref); |
621 | error5: | 621 | error5: |
622 | key_type_put(ktype); | 622 | key_type_put(ktype); |
623 | error4: | 623 | error4: |
624 | key_ref_put(dest_ref); | 624 | key_ref_put(dest_ref); |
625 | error3: | 625 | error3: |
626 | key_ref_put(keyring_ref); | 626 | key_ref_put(keyring_ref); |
627 | error2: | 627 | error2: |
628 | kfree(description); | 628 | kfree(description); |
629 | error: | 629 | error: |
630 | return ret; | 630 | return ret; |
631 | 631 | ||
632 | } /* end keyctl_keyring_search() */ | 632 | } /* end keyctl_keyring_search() */ |
@@ -673,7 +673,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | /* the key is probably readable - now try to read it */ | 675 | /* the key is probably readable - now try to read it */ |
676 | can_read_key: | 676 | can_read_key: |
677 | ret = key_validate(key); | 677 | ret = key_validate(key); |
678 | if (ret == 0) { | 678 | if (ret == 0) { |
679 | ret = -EOPNOTSUPP; | 679 | ret = -EOPNOTSUPP; |
@@ -686,9 +686,9 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
686 | } | 686 | } |
687 | } | 687 | } |
688 | 688 | ||
689 | error2: | 689 | error2: |
690 | key_put(key); | 690 | key_put(key); |
691 | error: | 691 | error: |
692 | return ret; | 692 | return ret; |
693 | 693 | ||
694 | } /* end keyctl_read_key() */ | 694 | } /* end keyctl_read_key() */ |
@@ -1282,26 +1282,19 @@ long keyctl_session_to_parent(void) | |||
1282 | 1282 | ||
1283 | /* the parent must have the same effective ownership and mustn't be | 1283 | /* the parent must have the same effective ownership and mustn't be |
1284 | * SUID/SGID */ | 1284 | * SUID/SGID */ |
1285 | if (pcred-> uid != mycred->euid || | 1285 | if (pcred->uid != mycred->euid || |
1286 | pcred->euid != mycred->euid || | 1286 | pcred->euid != mycred->euid || |
1287 | pcred->suid != mycred->euid || | 1287 | pcred->suid != mycred->euid || |
1288 | pcred-> gid != mycred->egid || | 1288 | pcred->gid != mycred->egid || |
1289 | pcred->egid != mycred->egid || | 1289 | pcred->egid != mycred->egid || |
1290 | pcred->sgid != mycred->egid) | 1290 | pcred->sgid != mycred->egid) |
1291 | goto not_permitted; | 1291 | goto not_permitted; |
1292 | 1292 | ||
1293 | /* the keyrings must have the same UID */ | 1293 | /* the keyrings must have the same UID */ |
1294 | if (pcred ->tgcred->session_keyring->uid != mycred->euid || | 1294 | if (pcred->tgcred->session_keyring->uid != mycred->euid || |
1295 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1295 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1296 | goto not_permitted; | 1296 | goto not_permitted; |
1297 | 1297 | ||
1298 | /* the LSM must permit the replacement of the parent's keyring with the | ||
1299 | * keyring from this process */ | ||
1300 | ret = security_key_session_to_parent(mycred, pcred, | ||
1301 | key_ref_to_ptr(keyring_r)); | ||
1302 | if (ret < 0) | ||
1303 | goto not_permitted; | ||
1304 | |||
1305 | /* if there's an already pending keyring replacement, then we replace | 1298 | /* if there's an already pending keyring replacement, then we replace |
1306 | * that */ | 1299 | * that */ |
1307 | oldcred = parent->replacement_session_keyring; | 1300 | oldcred = parent->replacement_session_keyring; |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 1e4b0037935c..ef03a82a0135 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <keys/keyring-type.h> | 19 | #include <keys/keyring-type.h> |
20 | #include <asm/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include "internal.h" | 21 | #include "internal.h" |
22 | 22 | ||
23 | #define rcu_dereference_locked_keyring(keyring) \ | 23 | #define rcu_dereference_locked_keyring(keyring) \ |
@@ -44,7 +44,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
44 | unsigned bucket = 0; | 44 | unsigned bucket = 0; |
45 | 45 | ||
46 | for (; *desc; desc++) | 46 | for (; *desc; desc++) |
47 | bucket += (unsigned char) *desc; | 47 | bucket += (unsigned char)*desc; |
48 | 48 | ||
49 | return bucket & (KEYRING_NAME_HASH_SIZE - 1); | 49 | return bucket & (KEYRING_NAME_HASH_SIZE - 1); |
50 | } | 50 | } |
@@ -175,12 +175,10 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
175 | { | 175 | { |
176 | struct keyring_list *klist; | 176 | struct keyring_list *klist; |
177 | 177 | ||
178 | if (keyring->description) { | 178 | if (keyring->description) |
179 | seq_puts(m, keyring->description); | 179 | seq_puts(m, keyring->description); |
180 | } | 180 | else |
181 | else { | ||
182 | seq_puts(m, "[anon]"); | 181 | seq_puts(m, "[anon]"); |
183 | } | ||
184 | 182 | ||
185 | rcu_read_lock(); | 183 | rcu_read_lock(); |
186 | klist = rcu_dereference(keyring->payload.subscriptions); | 184 | klist = rcu_dereference(keyring->payload.subscriptions); |
@@ -241,7 +239,7 @@ static long keyring_read(const struct key *keyring, | |||
241 | ret = qty; | 239 | ret = qty; |
242 | } | 240 | } |
243 | 241 | ||
244 | error: | 242 | error: |
245 | return ret; | 243 | return ret; |
246 | 244 | ||
247 | } /* end keyring_read() */ | 245 | } /* end keyring_read() */ |
@@ -310,7 +308,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
310 | key_check(keyring); | 308 | key_check(keyring); |
311 | 309 | ||
312 | /* top keyring must have search permission to begin the search */ | 310 | /* top keyring must have search permission to begin the search */ |
313 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); | 311 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); |
314 | if (err < 0) { | 312 | if (err < 0) { |
315 | key_ref = ERR_PTR(err); | 313 | key_ref = ERR_PTR(err); |
316 | goto error; | 314 | goto error; |
@@ -512,7 +510,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
512 | rcu_read_unlock(); | 510 | rcu_read_unlock(); |
513 | return ERR_PTR(-ENOKEY); | 511 | return ERR_PTR(-ENOKEY); |
514 | 512 | ||
515 | found: | 513 | found: |
516 | atomic_inc(&key->usage); | 514 | atomic_inc(&key->usage); |
517 | rcu_read_unlock(); | 515 | rcu_read_unlock(); |
518 | return make_key_ref(key, possessed); | 516 | return make_key_ref(key, possessed); |
@@ -602,7 +600,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
602 | sp = 0; | 600 | sp = 0; |
603 | 601 | ||
604 | /* start processing a new keyring */ | 602 | /* start processing a new keyring */ |
605 | descend: | 603 | descend: |
606 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) | 604 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) |
607 | goto not_this_keyring; | 605 | goto not_this_keyring; |
608 | 606 | ||
@@ -611,7 +609,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
611 | goto not_this_keyring; | 609 | goto not_this_keyring; |
612 | kix = 0; | 610 | kix = 0; |
613 | 611 | ||
614 | ascend: | 612 | ascend: |
615 | /* iterate through the remaining keys in this keyring */ | 613 | /* iterate through the remaining keys in this keyring */ |
616 | for (; kix < keylist->nkeys; kix++) { | 614 | for (; kix < keylist->nkeys; kix++) { |
617 | key = keylist->keys[kix]; | 615 | key = keylist->keys[kix]; |
@@ -637,7 +635,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
637 | 635 | ||
638 | /* the keyring we're looking at was disqualified or didn't contain a | 636 | /* the keyring we're looking at was disqualified or didn't contain a |
639 | * matching key */ | 637 | * matching key */ |
640 | not_this_keyring: | 638 | not_this_keyring: |
641 | if (sp > 0) { | 639 | if (sp > 0) { |
642 | /* resume the checking of a keyring higher up in the tree */ | 640 | /* resume the checking of a keyring higher up in the tree */ |
643 | sp--; | 641 | sp--; |
@@ -648,34 +646,20 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
648 | 646 | ||
649 | ret = 0; /* no cycles detected */ | 647 | ret = 0; /* no cycles detected */ |
650 | 648 | ||
651 | error: | 649 | error: |
652 | rcu_read_unlock(); | 650 | rcu_read_unlock(); |
653 | return ret; | 651 | return ret; |
654 | 652 | ||
655 | too_deep: | 653 | too_deep: |
656 | ret = -ELOOP; | 654 | ret = -ELOOP; |
657 | goto error; | 655 | goto error; |
658 | 656 | ||
659 | cycle_detected: | 657 | cycle_detected: |
660 | ret = -EDEADLK; | 658 | ret = -EDEADLK; |
661 | goto error; | 659 | goto error; |
662 | 660 | ||
663 | } /* end keyring_detect_cycle() */ | 661 | } /* end keyring_detect_cycle() */ |
664 | 662 | ||
665 | /*****************************************************************************/ | ||
666 | /* | ||
667 | * dispose of a keyring list after the RCU grace period | ||
668 | */ | ||
669 | static void keyring_link_rcu_disposal(struct rcu_head *rcu) | ||
670 | { | ||
671 | struct keyring_list *klist = | ||
672 | container_of(rcu, struct keyring_list, rcu); | ||
673 | |||
674 | kfree(klist); | ||
675 | |||
676 | } /* end keyring_link_rcu_disposal() */ | ||
677 | |||
678 | /*****************************************************************************/ | ||
679 | /* | 663 | /* |
680 | * dispose of a keyring list after the RCU grace period, freeing the unlinked | 664 | * dispose of a keyring list after the RCU grace period, freeing the unlinked |
681 | * key | 665 | * key |
@@ -685,55 +669,51 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | |||
685 | struct keyring_list *klist = | 669 | struct keyring_list *klist = |
686 | container_of(rcu, struct keyring_list, rcu); | 670 | container_of(rcu, struct keyring_list, rcu); |
687 | 671 | ||
688 | key_put(klist->keys[klist->delkey]); | 672 | if (klist->delkey != USHORT_MAX) |
673 | key_put(klist->keys[klist->delkey]); | ||
689 | kfree(klist); | 674 | kfree(klist); |
675 | } | ||
690 | 676 | ||
691 | } /* end keyring_unlink_rcu_disposal() */ | ||
692 | |||
693 | /*****************************************************************************/ | ||
694 | /* | 677 | /* |
695 | * link a key into to a keyring | 678 | * preallocate memory so that a key can be linked into to a keyring |
696 | * - must be called with the keyring's semaphore write-locked | ||
697 | * - discard already extant link to matching key if there is one | ||
698 | */ | 679 | */ |
699 | int __key_link(struct key *keyring, struct key *key) | 680 | int __key_link_begin(struct key *keyring, const struct key_type *type, |
681 | const char *description, | ||
682 | struct keyring_list **_prealloc) | ||
683 | __acquires(&keyring->sem) | ||
700 | { | 684 | { |
701 | struct keyring_list *klist, *nklist; | 685 | struct keyring_list *klist, *nklist; |
702 | unsigned max; | 686 | unsigned max; |
703 | size_t size; | 687 | size_t size; |
704 | int loop, ret; | 688 | int loop, ret; |
705 | 689 | ||
706 | ret = -EKEYREVOKED; | 690 | kenter("%d,%s,%s,", key_serial(keyring), type->name, description); |
707 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | ||
708 | goto error; | ||
709 | 691 | ||
710 | ret = -ENOTDIR; | ||
711 | if (keyring->type != &key_type_keyring) | 692 | if (keyring->type != &key_type_keyring) |
712 | goto error; | 693 | return -ENOTDIR; |
713 | 694 | ||
714 | /* serialise link/link calls to prevent parallel calls causing a | 695 | down_write(&keyring->sem); |
715 | * cycle when applied to two keyring in opposite orders */ | ||
716 | down_write(&keyring_serialise_link_sem); | ||
717 | 696 | ||
718 | /* check that we aren't going to create a cycle adding one keyring to | 697 | ret = -EKEYREVOKED; |
719 | * another */ | 698 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
720 | if (key->type == &key_type_keyring) { | 699 | goto error_krsem; |
721 | ret = keyring_detect_cycle(keyring, key); | 700 | |
722 | if (ret < 0) | 701 | /* serialise link/link calls to prevent parallel calls causing a cycle |
723 | goto error2; | 702 | * when linking two keyring in opposite orders */ |
724 | } | 703 | if (type == &key_type_keyring) |
704 | down_write(&keyring_serialise_link_sem); | ||
725 | 705 | ||
726 | /* see if there's a matching key we can displace */ | ||
727 | klist = rcu_dereference_locked_keyring(keyring); | 706 | klist = rcu_dereference_locked_keyring(keyring); |
728 | if (klist && klist->nkeys > 0) { | ||
729 | struct key_type *type = key->type; | ||
730 | 707 | ||
708 | /* see if there's a matching key we can displace */ | ||
709 | if (klist && klist->nkeys > 0) { | ||
731 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 710 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
732 | if (klist->keys[loop]->type == type && | 711 | if (klist->keys[loop]->type == type && |
733 | strcmp(klist->keys[loop]->description, | 712 | strcmp(klist->keys[loop]->description, |
734 | key->description) == 0 | 713 | description) == 0 |
735 | ) { | 714 | ) { |
736 | /* found a match - replace with new key */ | 715 | /* found a match - we'll replace this one with |
716 | * the new key */ | ||
737 | size = sizeof(struct key *) * klist->maxkeys; | 717 | size = sizeof(struct key *) * klist->maxkeys; |
738 | size += sizeof(*klist); | 718 | size += sizeof(*klist); |
739 | BUG_ON(size > PAGE_SIZE); | 719 | BUG_ON(size > PAGE_SIZE); |
@@ -741,22 +721,10 @@ int __key_link(struct key *keyring, struct key *key) | |||
741 | ret = -ENOMEM; | 721 | ret = -ENOMEM; |
742 | nklist = kmemdup(klist, size, GFP_KERNEL); | 722 | nklist = kmemdup(klist, size, GFP_KERNEL); |
743 | if (!nklist) | 723 | if (!nklist) |
744 | goto error2; | 724 | goto error_sem; |
745 | |||
746 | /* replace matched key */ | ||
747 | atomic_inc(&key->usage); | ||
748 | nklist->keys[loop] = key; | ||
749 | |||
750 | rcu_assign_pointer( | ||
751 | keyring->payload.subscriptions, | ||
752 | nklist); | ||
753 | |||
754 | /* dispose of the old keyring list and the | ||
755 | * displaced key */ | ||
756 | klist->delkey = loop; | ||
757 | call_rcu(&klist->rcu, | ||
758 | keyring_unlink_rcu_disposal); | ||
759 | 725 | ||
726 | /* note replacement slot */ | ||
727 | klist->delkey = nklist->delkey = loop; | ||
760 | goto done; | 728 | goto done; |
761 | } | 729 | } |
762 | } | 730 | } |
@@ -766,88 +734,167 @@ int __key_link(struct key *keyring, struct key *key) | |||
766 | ret = key_payload_reserve(keyring, | 734 | ret = key_payload_reserve(keyring, |
767 | keyring->datalen + KEYQUOTA_LINK_BYTES); | 735 | keyring->datalen + KEYQUOTA_LINK_BYTES); |
768 | if (ret < 0) | 736 | if (ret < 0) |
769 | goto error2; | 737 | goto error_sem; |
770 | 738 | ||
771 | if (klist && klist->nkeys < klist->maxkeys) { | 739 | if (klist && klist->nkeys < klist->maxkeys) { |
772 | /* there's sufficient slack space to add directly */ | 740 | /* there's sufficient slack space to append directly */ |
773 | atomic_inc(&key->usage); | 741 | nklist = NULL; |
774 | 742 | } else { | |
775 | klist->keys[klist->nkeys] = key; | ||
776 | smp_wmb(); | ||
777 | klist->nkeys++; | ||
778 | smp_wmb(); | ||
779 | } | ||
780 | else { | ||
781 | /* grow the key list */ | 743 | /* grow the key list */ |
782 | max = 4; | 744 | max = 4; |
783 | if (klist) | 745 | if (klist) |
784 | max += klist->maxkeys; | 746 | max += klist->maxkeys; |
785 | 747 | ||
786 | ret = -ENFILE; | 748 | ret = -ENFILE; |
787 | if (max > 65535) | 749 | if (max > USHORT_MAX - 1) |
788 | goto error3; | 750 | goto error_quota; |
789 | size = sizeof(*klist) + sizeof(struct key *) * max; | 751 | size = sizeof(*klist) + sizeof(struct key *) * max; |
790 | if (size > PAGE_SIZE) | 752 | if (size > PAGE_SIZE) |
791 | goto error3; | 753 | goto error_quota; |
792 | 754 | ||
793 | ret = -ENOMEM; | 755 | ret = -ENOMEM; |
794 | nklist = kmalloc(size, GFP_KERNEL); | 756 | nklist = kmalloc(size, GFP_KERNEL); |
795 | if (!nklist) | 757 | if (!nklist) |
796 | goto error3; | 758 | goto error_quota; |
797 | nklist->maxkeys = max; | ||
798 | nklist->nkeys = 0; | ||
799 | 759 | ||
760 | nklist->maxkeys = max; | ||
800 | if (klist) { | 761 | if (klist) { |
801 | nklist->nkeys = klist->nkeys; | 762 | memcpy(nklist->keys, klist->keys, |
802 | memcpy(nklist->keys, | ||
803 | klist->keys, | ||
804 | sizeof(struct key *) * klist->nkeys); | 763 | sizeof(struct key *) * klist->nkeys); |
764 | nklist->delkey = klist->nkeys; | ||
765 | nklist->nkeys = klist->nkeys + 1; | ||
766 | klist->delkey = USHORT_MAX; | ||
767 | } else { | ||
768 | nklist->nkeys = 1; | ||
769 | nklist->delkey = 0; | ||
805 | } | 770 | } |
806 | 771 | ||
807 | /* add the key into the new space */ | 772 | /* add the key into the new space */ |
808 | atomic_inc(&key->usage); | 773 | nklist->keys[nklist->delkey] = NULL; |
809 | nklist->keys[nklist->nkeys++] = key; | ||
810 | |||
811 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
812 | |||
813 | /* dispose of the old keyring list */ | ||
814 | if (klist) | ||
815 | call_rcu(&klist->rcu, keyring_link_rcu_disposal); | ||
816 | } | 774 | } |
817 | 775 | ||
818 | done: | 776 | done: |
819 | ret = 0; | 777 | *_prealloc = nklist; |
820 | error2: | 778 | kleave(" = 0"); |
821 | up_write(&keyring_serialise_link_sem); | 779 | return 0; |
822 | error: | ||
823 | return ret; | ||
824 | 780 | ||
825 | error3: | 781 | error_quota: |
826 | /* undo the quota changes */ | 782 | /* undo the quota changes */ |
827 | key_payload_reserve(keyring, | 783 | key_payload_reserve(keyring, |
828 | keyring->datalen - KEYQUOTA_LINK_BYTES); | 784 | keyring->datalen - KEYQUOTA_LINK_BYTES); |
829 | goto error2; | 785 | error_sem: |
786 | if (type == &key_type_keyring) | ||
787 | up_write(&keyring_serialise_link_sem); | ||
788 | error_krsem: | ||
789 | up_write(&keyring->sem); | ||
790 | kleave(" = %d", ret); | ||
791 | return ret; | ||
792 | } | ||
830 | 793 | ||
831 | } /* end __key_link() */ | 794 | /* |
795 | * check already instantiated keys aren't going to be a problem | ||
796 | * - the caller must have called __key_link_begin() | ||
797 | * - don't need to call this for keys that were created since __key_link_begin() | ||
798 | * was called | ||
799 | */ | ||
800 | int __key_link_check_live_key(struct key *keyring, struct key *key) | ||
801 | { | ||
802 | if (key->type == &key_type_keyring) | ||
803 | /* check that we aren't going to create a cycle by linking one | ||
804 | * keyring to another */ | ||
805 | return keyring_detect_cycle(keyring, key); | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | * link a key into to a keyring | ||
811 | * - must be called with __key_link_begin() having being called | ||
812 | * - discard already extant link to matching key if there is one | ||
813 | */ | ||
814 | void __key_link(struct key *keyring, struct key *key, | ||
815 | struct keyring_list **_prealloc) | ||
816 | { | ||
817 | struct keyring_list *klist, *nklist; | ||
818 | |||
819 | nklist = *_prealloc; | ||
820 | *_prealloc = NULL; | ||
821 | |||
822 | kenter("%d,%d,%p", keyring->serial, key->serial, nklist); | ||
823 | |||
824 | klist = rcu_dereference_protected(keyring->payload.subscriptions, | ||
825 | rwsem_is_locked(&keyring->sem)); | ||
826 | |||
827 | atomic_inc(&key->usage); | ||
828 | |||
829 | /* there's a matching key we can displace or an empty slot in a newly | ||
830 | * allocated list we can fill */ | ||
831 | if (nklist) { | ||
832 | kdebug("replace %hu/%hu/%hu", | ||
833 | nklist->delkey, nklist->nkeys, nklist->maxkeys); | ||
834 | |||
835 | nklist->keys[nklist->delkey] = key; | ||
836 | |||
837 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
838 | |||
839 | /* dispose of the old keyring list and, if there was one, the | ||
840 | * displaced key */ | ||
841 | if (klist) { | ||
842 | kdebug("dispose %hu/%hu/%hu", | ||
843 | klist->delkey, klist->nkeys, klist->maxkeys); | ||
844 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | ||
845 | } | ||
846 | } else { | ||
847 | /* there's sufficient slack space to append directly */ | ||
848 | klist->keys[klist->nkeys] = key; | ||
849 | smp_wmb(); | ||
850 | klist->nkeys++; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * finish linking a key into to a keyring | ||
856 | * - must be called with __key_link_begin() having being called | ||
857 | */ | ||
858 | void __key_link_end(struct key *keyring, struct key_type *type, | ||
859 | struct keyring_list *prealloc) | ||
860 | __releases(&keyring->sem) | ||
861 | { | ||
862 | BUG_ON(type == NULL); | ||
863 | BUG_ON(type->name == NULL); | ||
864 | kenter("%d,%s,%p", keyring->serial, type->name, prealloc); | ||
865 | |||
866 | if (type == &key_type_keyring) | ||
867 | up_write(&keyring_serialise_link_sem); | ||
868 | |||
869 | if (prealloc) { | ||
870 | kfree(prealloc); | ||
871 | key_payload_reserve(keyring, | ||
872 | keyring->datalen - KEYQUOTA_LINK_BYTES); | ||
873 | } | ||
874 | up_write(&keyring->sem); | ||
875 | } | ||
832 | 876 | ||
833 | /*****************************************************************************/ | ||
834 | /* | 877 | /* |
835 | * link a key to a keyring | 878 | * link a key to a keyring |
836 | */ | 879 | */ |
837 | int key_link(struct key *keyring, struct key *key) | 880 | int key_link(struct key *keyring, struct key *key) |
838 | { | 881 | { |
882 | struct keyring_list *prealloc; | ||
839 | int ret; | 883 | int ret; |
840 | 884 | ||
841 | key_check(keyring); | 885 | key_check(keyring); |
842 | key_check(key); | 886 | key_check(key); |
843 | 887 | ||
844 | down_write(&keyring->sem); | 888 | ret = __key_link_begin(keyring, key->type, key->description, &prealloc); |
845 | ret = __key_link(keyring, key); | 889 | if (ret == 0) { |
846 | up_write(&keyring->sem); | 890 | ret = __key_link_check_live_key(keyring, key); |
891 | if (ret == 0) | ||
892 | __key_link(keyring, key, &prealloc); | ||
893 | __key_link_end(keyring, key->type, prealloc); | ||
894 | } | ||
847 | 895 | ||
848 | return ret; | 896 | return ret; |
849 | 897 | } | |
850 | } /* end key_link() */ | ||
851 | 898 | ||
852 | EXPORT_SYMBOL(key_link); | 899 | EXPORT_SYMBOL(key_link); |
853 | 900 | ||
diff --git a/security/keys/permission.c b/security/keys/permission.c index 0ed802c9e698..28645502cd0d 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -109,7 +109,7 @@ int key_validate(struct key *key) | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | error: | 112 | error: |
113 | return ret; | 113 | return ret; |
114 | 114 | ||
115 | } /* end key_validate() */ | 115 | } /* end key_validate() */ |
diff --git a/security/keys/proc.c b/security/keys/proc.c index 706d63f4f185..068b66ea2f1b 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -306,7 +306,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
306 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | 306 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) |
307 | { | 307 | { |
308 | (*_pos)++; | 308 | (*_pos)++; |
309 | return key_user_next((struct rb_node *) v); | 309 | return key_user_next((struct rb_node *)v); |
310 | } | 310 | } |
311 | 311 | ||
312 | static void proc_key_users_stop(struct seq_file *p, void *v) | 312 | static void proc_key_users_stop(struct seq_file *p, void *v) |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 06c2ccf26ed3..20a38fed61b1 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -508,7 +508,7 @@ try_again: | |||
508 | 508 | ||
509 | ret = install_thread_keyring(); | 509 | ret = install_thread_keyring(); |
510 | if (ret < 0) { | 510 | if (ret < 0) { |
511 | key = ERR_PTR(ret); | 511 | key_ref = ERR_PTR(ret); |
512 | goto error; | 512 | goto error; |
513 | } | 513 | } |
514 | goto reget_creds; | 514 | goto reget_creds; |
@@ -526,7 +526,7 @@ try_again: | |||
526 | 526 | ||
527 | ret = install_process_keyring(); | 527 | ret = install_process_keyring(); |
528 | if (ret < 0) { | 528 | if (ret < 0) { |
529 | key = ERR_PTR(ret); | 529 | key_ref = ERR_PTR(ret); |
530 | goto error; | 530 | goto error; |
531 | } | 531 | } |
532 | goto reget_creds; | 532 | goto reget_creds; |
@@ -585,7 +585,7 @@ try_again: | |||
585 | 585 | ||
586 | case KEY_SPEC_GROUP_KEYRING: | 586 | case KEY_SPEC_GROUP_KEYRING: |
587 | /* group keyrings are not yet supported */ | 587 | /* group keyrings are not yet supported */ |
588 | key = ERR_PTR(-EINVAL); | 588 | key_ref = ERR_PTR(-EINVAL); |
589 | goto error; | 589 | goto error; |
590 | 590 | ||
591 | case KEY_SPEC_REQKEY_AUTH_KEY: | 591 | case KEY_SPEC_REQKEY_AUTH_KEY: |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index d8c1a6a0fb08..f656e9c069e3 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -299,12 +299,15 @@ static int construct_alloc_key(struct key_type *type, | |||
299 | struct key_user *user, | 299 | struct key_user *user, |
300 | struct key **_key) | 300 | struct key **_key) |
301 | { | 301 | { |
302 | struct keyring_list *prealloc; | ||
302 | const struct cred *cred = current_cred(); | 303 | const struct cred *cred = current_cred(); |
303 | struct key *key; | 304 | struct key *key; |
304 | key_ref_t key_ref; | 305 | key_ref_t key_ref; |
306 | int ret; | ||
305 | 307 | ||
306 | kenter("%s,%s,,,", type->name, description); | 308 | kenter("%s,%s,,,", type->name, description); |
307 | 309 | ||
310 | *_key = NULL; | ||
308 | mutex_lock(&user->cons_lock); | 311 | mutex_lock(&user->cons_lock); |
309 | 312 | ||
310 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 313 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
@@ -314,8 +317,12 @@ static int construct_alloc_key(struct key_type *type, | |||
314 | 317 | ||
315 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 318 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
316 | 319 | ||
317 | if (dest_keyring) | 320 | if (dest_keyring) { |
318 | down_write(&dest_keyring->sem); | 321 | ret = __key_link_begin(dest_keyring, type, description, |
322 | &prealloc); | ||
323 | if (ret < 0) | ||
324 | goto link_prealloc_failed; | ||
325 | } | ||
319 | 326 | ||
320 | /* attach the key to the destination keyring under lock, but we do need | 327 | /* attach the key to the destination keyring under lock, but we do need |
321 | * to do another check just in case someone beat us to it whilst we | 328 | * to do another check just in case someone beat us to it whilst we |
@@ -327,31 +334,49 @@ static int construct_alloc_key(struct key_type *type, | |||
327 | goto key_already_present; | 334 | goto key_already_present; |
328 | 335 | ||
329 | if (dest_keyring) | 336 | if (dest_keyring) |
330 | __key_link(dest_keyring, key); | 337 | __key_link(dest_keyring, key, &prealloc); |
331 | 338 | ||
332 | mutex_unlock(&key_construction_mutex); | 339 | mutex_unlock(&key_construction_mutex); |
333 | if (dest_keyring) | 340 | if (dest_keyring) |
334 | up_write(&dest_keyring->sem); | 341 | __key_link_end(dest_keyring, type, prealloc); |
335 | mutex_unlock(&user->cons_lock); | 342 | mutex_unlock(&user->cons_lock); |
336 | *_key = key; | 343 | *_key = key; |
337 | kleave(" = 0 [%d]", key_serial(key)); | 344 | kleave(" = 0 [%d]", key_serial(key)); |
338 | return 0; | 345 | return 0; |
339 | 346 | ||
347 | /* the key is now present - we tell the caller that we found it by | ||
348 | * returning -EINPROGRESS */ | ||
340 | key_already_present: | 349 | key_already_present: |
350 | key_put(key); | ||
341 | mutex_unlock(&key_construction_mutex); | 351 | mutex_unlock(&key_construction_mutex); |
352 | key = key_ref_to_ptr(key_ref); | ||
342 | if (dest_keyring) { | 353 | if (dest_keyring) { |
343 | __key_link(dest_keyring, key_ref_to_ptr(key_ref)); | 354 | ret = __key_link_check_live_key(dest_keyring, key); |
344 | up_write(&dest_keyring->sem); | 355 | if (ret == 0) |
356 | __key_link(dest_keyring, key, &prealloc); | ||
357 | __key_link_end(dest_keyring, type, prealloc); | ||
358 | if (ret < 0) | ||
359 | goto link_check_failed; | ||
345 | } | 360 | } |
346 | mutex_unlock(&user->cons_lock); | 361 | mutex_unlock(&user->cons_lock); |
347 | key_put(key); | 362 | *_key = key; |
348 | *_key = key = key_ref_to_ptr(key_ref); | ||
349 | kleave(" = -EINPROGRESS [%d]", key_serial(key)); | 363 | kleave(" = -EINPROGRESS [%d]", key_serial(key)); |
350 | return -EINPROGRESS; | 364 | return -EINPROGRESS; |
351 | 365 | ||
366 | link_check_failed: | ||
367 | mutex_unlock(&user->cons_lock); | ||
368 | key_put(key); | ||
369 | kleave(" = %d [linkcheck]", ret); | ||
370 | return ret; | ||
371 | |||
372 | link_prealloc_failed: | ||
373 | up_write(&dest_keyring->sem); | ||
374 | mutex_unlock(&user->cons_lock); | ||
375 | kleave(" = %d [prelink]", ret); | ||
376 | return ret; | ||
377 | |||
352 | alloc_failed: | 378 | alloc_failed: |
353 | mutex_unlock(&user->cons_lock); | 379 | mutex_unlock(&user->cons_lock); |
354 | *_key = NULL; | ||
355 | kleave(" = %ld", PTR_ERR(key)); | 380 | kleave(" = %ld", PTR_ERR(key)); |
356 | return PTR_ERR(key); | 381 | return PTR_ERR(key); |
357 | } | 382 | } |
@@ -390,6 +415,10 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
390 | kdebug("cons failed"); | 415 | kdebug("cons failed"); |
391 | goto construction_failed; | 416 | goto construction_failed; |
392 | } | 417 | } |
418 | } else if (ret == -EINPROGRESS) { | ||
419 | ret = 0; | ||
420 | } else { | ||
421 | key = ERR_PTR(ret); | ||
393 | } | 422 | } |
394 | 423 | ||
395 | key_put(dest_keyring); | 424 | key_put(dest_keyring); |
@@ -422,6 +451,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
422 | const struct cred *cred = current_cred(); | 451 | const struct cred *cred = current_cred(); |
423 | struct key *key; | 452 | struct key *key; |
424 | key_ref_t key_ref; | 453 | key_ref_t key_ref; |
454 | int ret; | ||
425 | 455 | ||
426 | kenter("%s,%s,%p,%zu,%p,%p,%lx", | 456 | kenter("%s,%s,%p,%zu,%p,%p,%lx", |
427 | type->name, description, callout_info, callout_len, aux, | 457 | type->name, description, callout_info, callout_len, aux, |
@@ -435,8 +465,13 @@ struct key *request_key_and_link(struct key_type *type, | |||
435 | key = key_ref_to_ptr(key_ref); | 465 | key = key_ref_to_ptr(key_ref); |
436 | if (dest_keyring) { | 466 | if (dest_keyring) { |
437 | construct_get_dest_keyring(&dest_keyring); | 467 | construct_get_dest_keyring(&dest_keyring); |
438 | key_link(dest_keyring, key); | 468 | ret = key_link(dest_keyring, key); |
439 | key_put(dest_keyring); | 469 | key_put(dest_keyring); |
470 | if (ret < 0) { | ||
471 | key_put(key); | ||
472 | key = ERR_PTR(ret); | ||
473 | goto error; | ||
474 | } | ||
440 | } | 475 | } |
441 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 476 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
442 | key = ERR_CAST(key_ref); | 477 | key = ERR_CAST(key_ref); |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 893365b79a29..908aa712816a 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -221,7 +221,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
221 | } | 221 | } |
222 | 222 | ||
223 | switch (a->type) { | 223 | switch (a->type) { |
224 | case LSM_AUDIT_NO_AUDIT: | 224 | case LSM_AUDIT_DATA_NONE: |
225 | return; | 225 | return; |
226 | case LSM_AUDIT_DATA_IPC: | 226 | case LSM_AUDIT_DATA_IPC: |
227 | audit_log_format(ab, " key=%d ", a->u.ipc_id); | 227 | audit_log_format(ab, " key=%d ", a->u.ipc_id); |
diff --git a/security/security.c b/security/security.c index 687c6fd14bb6..351942a4ca0e 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -23,14 +23,14 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | |||
23 | CONFIG_DEFAULT_SECURITY; | 23 | CONFIG_DEFAULT_SECURITY; |
24 | 24 | ||
25 | /* things that live in capability.c */ | 25 | /* things that live in capability.c */ |
26 | extern void security_fixup_ops(struct security_operations *ops); | 26 | extern void __init security_fixup_ops(struct security_operations *ops); |
27 | 27 | ||
28 | static struct security_operations *security_ops; | 28 | static struct security_operations *security_ops; |
29 | static struct security_operations default_security_ops = { | 29 | static struct security_operations default_security_ops = { |
30 | .name = "default", | 30 | .name = "default", |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static inline int verify(struct security_operations *ops) | 33 | static inline int __init verify(struct security_operations *ops) |
34 | { | 34 | { |
35 | /* verify the security_operations structure exists */ | 35 | /* verify the security_operations structure exists */ |
36 | if (!ops) | 36 | if (!ops) |
@@ -117,7 +117,7 @@ int __init security_module_enable(struct security_operations *ops) | |||
117 | * If there is already a security module registered with the kernel, | 117 | * If there is already a security module registered with the kernel, |
118 | * an error will be returned. Otherwise %0 is returned on success. | 118 | * an error will be returned. Otherwise %0 is returned on success. |
119 | */ | 119 | */ |
120 | int register_security(struct security_operations *ops) | 120 | int __init register_security(struct security_operations *ops) |
121 | { | 121 | { |
122 | if (verify(ops)) { | 122 | if (verify(ops)) { |
123 | printk(KERN_DEBUG "%s could not verify " | 123 | printk(KERN_DEBUG "%s could not verify " |
@@ -190,11 +190,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap) | |||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | int security_acct(struct file *file) | ||
194 | { | ||
195 | return security_ops->acct(file); | ||
196 | } | ||
197 | |||
198 | int security_sysctl(struct ctl_table *table, int op) | 193 | int security_sysctl(struct ctl_table *table, int op) |
199 | { | 194 | { |
200 | return security_ops->sysctl(table, op); | 195 | return security_ops->sysctl(table, op); |
@@ -306,46 +301,16 @@ int security_sb_mount(char *dev_name, struct path *path, | |||
306 | return security_ops->sb_mount(dev_name, path, type, flags, data); | 301 | return security_ops->sb_mount(dev_name, path, type, flags, data); |
307 | } | 302 | } |
308 | 303 | ||
309 | int security_sb_check_sb(struct vfsmount *mnt, struct path *path) | ||
310 | { | ||
311 | return security_ops->sb_check_sb(mnt, path); | ||
312 | } | ||
313 | |||
314 | int security_sb_umount(struct vfsmount *mnt, int flags) | 304 | int security_sb_umount(struct vfsmount *mnt, int flags) |
315 | { | 305 | { |
316 | return security_ops->sb_umount(mnt, flags); | 306 | return security_ops->sb_umount(mnt, flags); |
317 | } | 307 | } |
318 | 308 | ||
319 | void security_sb_umount_close(struct vfsmount *mnt) | ||
320 | { | ||
321 | security_ops->sb_umount_close(mnt); | ||
322 | } | ||
323 | |||
324 | void security_sb_umount_busy(struct vfsmount *mnt) | ||
325 | { | ||
326 | security_ops->sb_umount_busy(mnt); | ||
327 | } | ||
328 | |||
329 | void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data) | ||
330 | { | ||
331 | security_ops->sb_post_remount(mnt, flags, data); | ||
332 | } | ||
333 | |||
334 | void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint) | ||
335 | { | ||
336 | security_ops->sb_post_addmount(mnt, mountpoint); | ||
337 | } | ||
338 | |||
339 | int security_sb_pivotroot(struct path *old_path, struct path *new_path) | 309 | int security_sb_pivotroot(struct path *old_path, struct path *new_path) |
340 | { | 310 | { |
341 | return security_ops->sb_pivotroot(old_path, new_path); | 311 | return security_ops->sb_pivotroot(old_path, new_path); |
342 | } | 312 | } |
343 | 313 | ||
344 | void security_sb_post_pivotroot(struct path *old_path, struct path *new_path) | ||
345 | { | ||
346 | security_ops->sb_post_pivotroot(old_path, new_path); | ||
347 | } | ||
348 | |||
349 | int security_sb_set_mnt_opts(struct super_block *sb, | 314 | int security_sb_set_mnt_opts(struct super_block *sb, |
350 | struct security_mnt_opts *opts) | 315 | struct security_mnt_opts *opts) |
351 | { | 316 | { |
@@ -580,13 +545,6 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
580 | return security_ops->inode_getattr(mnt, dentry); | 545 | return security_ops->inode_getattr(mnt, dentry); |
581 | } | 546 | } |
582 | 547 | ||
583 | void security_inode_delete(struct inode *inode) | ||
584 | { | ||
585 | if (unlikely(IS_PRIVATE(inode))) | ||
586 | return; | ||
587 | security_ops->inode_delete(inode); | ||
588 | } | ||
589 | |||
590 | int security_inode_setxattr(struct dentry *dentry, const char *name, | 548 | int security_inode_setxattr(struct dentry *dentry, const char *name, |
591 | const void *value, size_t size, int flags) | 549 | const void *value, size_t size, int flags) |
592 | { | 550 | { |
@@ -749,11 +707,6 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) | |||
749 | return security_ops->cred_prepare(new, old, gfp); | 707 | return security_ops->cred_prepare(new, old, gfp); |
750 | } | 708 | } |
751 | 709 | ||
752 | void security_commit_creds(struct cred *new, const struct cred *old) | ||
753 | { | ||
754 | security_ops->cred_commit(new, old); | ||
755 | } | ||
756 | |||
757 | void security_transfer_creds(struct cred *new, const struct cred *old) | 710 | void security_transfer_creds(struct cred *new, const struct cred *old) |
758 | { | 711 | { |
759 | security_ops->cred_transfer(new, old); | 712 | security_ops->cred_transfer(new, old); |
@@ -774,22 +727,12 @@ int security_kernel_module_request(char *kmod_name) | |||
774 | return security_ops->kernel_module_request(kmod_name); | 727 | return security_ops->kernel_module_request(kmod_name); |
775 | } | 728 | } |
776 | 729 | ||
777 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | ||
778 | { | ||
779 | return security_ops->task_setuid(id0, id1, id2, flags); | ||
780 | } | ||
781 | |||
782 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 730 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
783 | int flags) | 731 | int flags) |
784 | { | 732 | { |
785 | return security_ops->task_fix_setuid(new, old, flags); | 733 | return security_ops->task_fix_setuid(new, old, flags); |
786 | } | 734 | } |
787 | 735 | ||
788 | int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | ||
789 | { | ||
790 | return security_ops->task_setgid(id0, id1, id2, flags); | ||
791 | } | ||
792 | |||
793 | int security_task_setpgid(struct task_struct *p, pid_t pgid) | 736 | int security_task_setpgid(struct task_struct *p, pid_t pgid) |
794 | { | 737 | { |
795 | return security_ops->task_setpgid(p, pgid); | 738 | return security_ops->task_setpgid(p, pgid); |
@@ -811,11 +754,6 @@ void security_task_getsecid(struct task_struct *p, u32 *secid) | |||
811 | } | 754 | } |
812 | EXPORT_SYMBOL(security_task_getsecid); | 755 | EXPORT_SYMBOL(security_task_getsecid); |
813 | 756 | ||
814 | int security_task_setgroups(struct group_info *group_info) | ||
815 | { | ||
816 | return security_ops->task_setgroups(group_info); | ||
817 | } | ||
818 | |||
819 | int security_task_setnice(struct task_struct *p, int nice) | 757 | int security_task_setnice(struct task_struct *p, int nice) |
820 | { | 758 | { |
821 | return security_ops->task_setnice(p, nice); | 759 | return security_ops->task_setnice(p, nice); |
@@ -1319,13 +1257,6 @@ int security_key_getsecurity(struct key *key, char **_buffer) | |||
1319 | return security_ops->key_getsecurity(key, _buffer); | 1257 | return security_ops->key_getsecurity(key, _buffer); |
1320 | } | 1258 | } |
1321 | 1259 | ||
1322 | int security_key_session_to_parent(const struct cred *cred, | ||
1323 | const struct cred *parent_cred, | ||
1324 | struct key *key) | ||
1325 | { | ||
1326 | return security_ops->key_session_to_parent(cred, parent_cred, key); | ||
1327 | } | ||
1328 | |||
1329 | #endif /* CONFIG_KEYS */ | 1260 | #endif /* CONFIG_KEYS */ |
1330 | 1261 | ||
1331 | #ifdef CONFIG_AUDIT | 1262 | #ifdef CONFIG_AUDIT |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 989fef82563a..7f1a304712a9 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -499,8 +499,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
499 | return; | 499 | return; |
500 | if (!a) { | 500 | if (!a) { |
501 | a = &stack_data; | 501 | a = &stack_data; |
502 | memset(a, 0, sizeof(*a)); | 502 | COMMON_AUDIT_DATA_INIT(a, NONE); |
503 | a->type = LSM_AUDIT_NO_AUDIT; | ||
504 | } | 503 | } |
505 | a->selinux_audit_data.tclass = tclass; | 504 | a->selinux_audit_data.tclass = tclass; |
506 | a->selinux_audit_data.requested = requested; | 505 | a->selinux_audit_data.requested = requested; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5feecb41009d..a03fd74602b4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -293,28 +293,28 @@ static void superblock_free_security(struct super_block *sb) | |||
293 | 293 | ||
294 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 294 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
295 | { | 295 | { |
296 | struct sk_security_struct *ssec; | 296 | struct sk_security_struct *sksec; |
297 | 297 | ||
298 | ssec = kzalloc(sizeof(*ssec), priority); | 298 | sksec = kzalloc(sizeof(*sksec), priority); |
299 | if (!ssec) | 299 | if (!sksec) |
300 | return -ENOMEM; | 300 | return -ENOMEM; |
301 | 301 | ||
302 | ssec->peer_sid = SECINITSID_UNLABELED; | 302 | sksec->peer_sid = SECINITSID_UNLABELED; |
303 | ssec->sid = SECINITSID_UNLABELED; | 303 | sksec->sid = SECINITSID_UNLABELED; |
304 | sk->sk_security = ssec; | 304 | sk->sk_security = sksec; |
305 | 305 | ||
306 | selinux_netlbl_sk_security_reset(ssec); | 306 | selinux_netlbl_sk_security_reset(sksec); |
307 | 307 | ||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | static void sk_free_security(struct sock *sk) | 311 | static void sk_free_security(struct sock *sk) |
312 | { | 312 | { |
313 | struct sk_security_struct *ssec = sk->sk_security; | 313 | struct sk_security_struct *sksec = sk->sk_security; |
314 | 314 | ||
315 | sk->sk_security = NULL; | 315 | sk->sk_security = NULL; |
316 | selinux_netlbl_sk_security_free(ssec); | 316 | selinux_netlbl_sk_security_free(sksec); |
317 | kfree(ssec); | 317 | kfree(sksec); |
318 | } | 318 | } |
319 | 319 | ||
320 | /* The security server must be initialized before | 320 | /* The security server must be initialized before |
@@ -323,7 +323,7 @@ extern int ss_initialized; | |||
323 | 323 | ||
324 | /* The file system's label must be initialized prior to use. */ | 324 | /* The file system's label must be initialized prior to use. */ |
325 | 325 | ||
326 | static char *labeling_behaviors[6] = { | 326 | static const char *labeling_behaviors[6] = { |
327 | "uses xattr", | 327 | "uses xattr", |
328 | "uses transition SIDs", | 328 | "uses transition SIDs", |
329 | "uses task SIDs", | 329 | "uses task SIDs", |
@@ -2999,13 +2999,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
2999 | return file_has_perm(cred, file, av); | 2999 | return file_has_perm(cred, file, av); |
3000 | } | 3000 | } |
3001 | 3001 | ||
3002 | static int default_noexec; | ||
3003 | |||
3002 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3004 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
3003 | { | 3005 | { |
3004 | const struct cred *cred = current_cred(); | 3006 | const struct cred *cred = current_cred(); |
3005 | int rc = 0; | 3007 | int rc = 0; |
3006 | 3008 | ||
3007 | #ifndef CONFIG_PPC32 | 3009 | if (default_noexec && |
3008 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 3010 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
3009 | /* | 3011 | /* |
3010 | * We are making executable an anonymous mapping or a | 3012 | * We are making executable an anonymous mapping or a |
3011 | * private file mapping that will also be writable. | 3013 | * private file mapping that will also be writable. |
@@ -3015,7 +3017,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3015 | if (rc) | 3017 | if (rc) |
3016 | goto error; | 3018 | goto error; |
3017 | } | 3019 | } |
3018 | #endif | ||
3019 | 3020 | ||
3020 | if (file) { | 3021 | if (file) { |
3021 | /* read access is always possible with a mapping */ | 3022 | /* read access is always possible with a mapping */ |
@@ -3076,8 +3077,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3076 | if (selinux_checkreqprot) | 3077 | if (selinux_checkreqprot) |
3077 | prot = reqprot; | 3078 | prot = reqprot; |
3078 | 3079 | ||
3079 | #ifndef CONFIG_PPC32 | 3080 | if (default_noexec && |
3080 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3081 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
3081 | int rc = 0; | 3082 | int rc = 0; |
3082 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3083 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3083 | vma->vm_end <= vma->vm_mm->brk) { | 3084 | vma->vm_end <= vma->vm_mm->brk) { |
@@ -3099,7 +3100,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3099 | if (rc) | 3100 | if (rc) |
3100 | return rc; | 3101 | return rc; |
3101 | } | 3102 | } |
3102 | #endif | ||
3103 | 3103 | ||
3104 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3104 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
3105 | } | 3105 | } |
@@ -4002,7 +4002,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
4002 | struct socket *other, | 4002 | struct socket *other, |
4003 | struct sock *newsk) | 4003 | struct sock *newsk) |
4004 | { | 4004 | { |
4005 | struct sk_security_struct *ssec; | 4005 | struct sk_security_struct *sksec; |
4006 | struct inode_security_struct *isec; | 4006 | struct inode_security_struct *isec; |
4007 | struct inode_security_struct *other_isec; | 4007 | struct inode_security_struct *other_isec; |
4008 | struct common_audit_data ad; | 4008 | struct common_audit_data ad; |
@@ -4021,13 +4021,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
4021 | return err; | 4021 | return err; |
4022 | 4022 | ||
4023 | /* connecting socket */ | 4023 | /* connecting socket */ |
4024 | ssec = sock->sk->sk_security; | 4024 | sksec = sock->sk->sk_security; |
4025 | ssec->peer_sid = other_isec->sid; | 4025 | sksec->peer_sid = other_isec->sid; |
4026 | 4026 | ||
4027 | /* server child socket */ | 4027 | /* server child socket */ |
4028 | ssec = newsk->sk_security; | 4028 | sksec = newsk->sk_security; |
4029 | ssec->peer_sid = isec->sid; | 4029 | sksec->peer_sid = isec->sid; |
4030 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 4030 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); |
4031 | 4031 | ||
4032 | return err; | 4032 | return err; |
4033 | } | 4033 | } |
@@ -4190,7 +4190,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4190 | int err = 0; | 4190 | int err = 0; |
4191 | char *scontext; | 4191 | char *scontext; |
4192 | u32 scontext_len; | 4192 | u32 scontext_len; |
4193 | struct sk_security_struct *ssec; | 4193 | struct sk_security_struct *sksec; |
4194 | struct inode_security_struct *isec; | 4194 | struct inode_security_struct *isec; |
4195 | u32 peer_sid = SECSID_NULL; | 4195 | u32 peer_sid = SECSID_NULL; |
4196 | 4196 | ||
@@ -4198,8 +4198,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4198 | 4198 | ||
4199 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4199 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4200 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4200 | isec->sclass == SECCLASS_TCP_SOCKET) { |
4201 | ssec = sock->sk->sk_security; | 4201 | sksec = sock->sk->sk_security; |
4202 | peer_sid = ssec->peer_sid; | 4202 | peer_sid = sksec->peer_sid; |
4203 | } | 4203 | } |
4204 | if (peer_sid == SECSID_NULL) { | 4204 | if (peer_sid == SECSID_NULL) { |
4205 | err = -ENOPROTOOPT; | 4205 | err = -ENOPROTOOPT; |
@@ -4266,14 +4266,14 @@ static void selinux_sk_free_security(struct sock *sk) | |||
4266 | 4266 | ||
4267 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4267 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
4268 | { | 4268 | { |
4269 | struct sk_security_struct *ssec = sk->sk_security; | 4269 | struct sk_security_struct *sksec = sk->sk_security; |
4270 | struct sk_security_struct *newssec = newsk->sk_security; | 4270 | struct sk_security_struct *newsksec = newsk->sk_security; |
4271 | 4271 | ||
4272 | newssec->sid = ssec->sid; | 4272 | newsksec->sid = sksec->sid; |
4273 | newssec->peer_sid = ssec->peer_sid; | 4273 | newsksec->peer_sid = sksec->peer_sid; |
4274 | newssec->sclass = ssec->sclass; | 4274 | newsksec->sclass = sksec->sclass; |
4275 | 4275 | ||
4276 | selinux_netlbl_sk_security_reset(newssec); | 4276 | selinux_netlbl_sk_security_reset(newsksec); |
4277 | } | 4277 | } |
4278 | 4278 | ||
4279 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4279 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
@@ -5662,6 +5662,8 @@ static __init int selinux_init(void) | |||
5662 | /* Set the security state for the initial task. */ | 5662 | /* Set the security state for the initial task. */ |
5663 | cred_init_security(); | 5663 | cred_init_security(); |
5664 | 5664 | ||
5665 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
5666 | |||
5665 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5667 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5666 | sizeof(struct inode_security_struct), | 5668 | sizeof(struct inode_security_struct), |
5667 | 0, SLAB_PANIC, NULL); | 5669 | 0, SLAB_PANIC, NULL); |
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index d4fac82793ae..a59b64e3fd02 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | 1 | /* This file is automatically generated. Do not edit. */ |
2 | static char *initial_sid_to_string[] = | 2 | static const char *initial_sid_to_string[] = |
3 | { | 3 | { |
4 | "null", | 4 | "null", |
5 | "kernel", | 5 | "kernel", |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 8d7384280a7a..cf2f628e6e28 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
@@ -42,8 +42,8 @@ void selinux_netlbl_cache_invalidate(void); | |||
42 | 42 | ||
43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); | 43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); |
44 | 44 | ||
45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); | 45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); |
46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec); | 46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); |
47 | 47 | ||
48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
49 | u16 family, | 49 | u16 family, |
@@ -79,13 +79,13 @@ static inline void selinux_netlbl_err(struct sk_buff *skb, | |||
79 | } | 79 | } |
80 | 80 | ||
81 | static inline void selinux_netlbl_sk_security_free( | 81 | static inline void selinux_netlbl_sk_security_free( |
82 | struct sk_security_struct *ssec) | 82 | struct sk_security_struct *sksec) |
83 | { | 83 | { |
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline void selinux_netlbl_sk_security_reset( | 87 | static inline void selinux_netlbl_sk_security_reset( |
88 | struct sk_security_struct *ssec) | 88 | struct sk_security_struct *sksec) |
89 | { | 89 | { |
90 | return; | 90 | return; |
91 | } | 91 | } |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 628da72ee763..1c2fc46544bf 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -132,21 +132,21 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) | |||
132 | 132 | ||
133 | /** | 133 | /** |
134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields | 134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields |
135 | * @sssec: the sk_security_struct | 135 | * @sksec: the sk_security_struct |
136 | * | 136 | * |
137 | * Description: | 137 | * Description: |
138 | * Free all of the memory in the NetLabel fields of a sk_security_struct. | 138 | * Free all of the memory in the NetLabel fields of a sk_security_struct. |
139 | * | 139 | * |
140 | */ | 140 | */ |
141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | 141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) |
142 | { | 142 | { |
143 | if (ssec->nlbl_secattr != NULL) | 143 | if (sksec->nlbl_secattr != NULL) |
144 | netlbl_secattr_free(ssec->nlbl_secattr); | 144 | netlbl_secattr_free(sksec->nlbl_secattr); |
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields | 148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields |
149 | * @ssec: the sk_security_struct | 149 | * @sksec: the sk_security_struct |
150 | * @family: the socket family | 150 | * @family: the socket family |
151 | * | 151 | * |
152 | * Description: | 152 | * Description: |
@@ -154,9 +154,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | |||
154 | * The caller is responsibile for all the NetLabel sk_security_struct locking. | 154 | * The caller is responsibile for all the NetLabel sk_security_struct locking. |
155 | * | 155 | * |
156 | */ | 156 | */ |
157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) | 157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) |
158 | { | 158 | { |
159 | ssec->nlbl_state = NLBL_UNSET; | 159 | sksec->nlbl_state = NLBL_UNSET; |
160 | } | 160 | } |
161 | 161 | ||
162 | /** | 162 | /** |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 0e147b6914ad..36ac257cec9a 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/list.h> | ||
18 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
19 | #include <linux/netlink.h> | 18 | #include <linux/netlink.h> |
20 | #include <linux/selinux_netlink.h> | 19 | #include <linux/selinux_netlink.h> |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index dd7cc6de77f9..75ec0c6ebacd 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
16 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
17 | #include <linux/if.h> | 16 | #include <linux/if.h> |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cd191bbec03c..0293843f7eda 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -503,11 +503,11 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
503 | return length; | 503 | return length; |
504 | 504 | ||
505 | length = -ENOMEM; | 505 | length = -ENOMEM; |
506 | scon = kzalloc(size+1, GFP_KERNEL); | 506 | scon = kzalloc(size + 1, GFP_KERNEL); |
507 | if (!scon) | 507 | if (!scon) |
508 | return length; | 508 | return length; |
509 | 509 | ||
510 | tcon = kzalloc(size+1, GFP_KERNEL); | 510 | tcon = kzalloc(size + 1, GFP_KERNEL); |
511 | if (!tcon) | 511 | if (!tcon) |
512 | goto out; | 512 | goto out; |
513 | 513 | ||
@@ -515,10 +515,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
516 | goto out2; | 516 | goto out2; |
517 | 517 | ||
518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 518 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
519 | if (length < 0) | 519 | if (length < 0) |
520 | goto out2; | 520 | goto out2; |
521 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 521 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
522 | if (length < 0) | 522 | if (length < 0) |
523 | goto out2; | 523 | goto out2; |
524 | 524 | ||
@@ -550,11 +550,11 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
550 | return length; | 550 | return length; |
551 | 551 | ||
552 | length = -ENOMEM; | 552 | length = -ENOMEM; |
553 | scon = kzalloc(size+1, GFP_KERNEL); | 553 | scon = kzalloc(size + 1, GFP_KERNEL); |
554 | if (!scon) | 554 | if (!scon) |
555 | return length; | 555 | return length; |
556 | 556 | ||
557 | tcon = kzalloc(size+1, GFP_KERNEL); | 557 | tcon = kzalloc(size + 1, GFP_KERNEL); |
558 | if (!tcon) | 558 | if (!tcon) |
559 | goto out; | 559 | goto out; |
560 | 560 | ||
@@ -562,10 +562,10 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
562 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 562 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
563 | goto out2; | 563 | goto out2; |
564 | 564 | ||
565 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 565 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
566 | if (length < 0) | 566 | if (length < 0) |
567 | goto out2; | 567 | goto out2; |
568 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 568 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
569 | if (length < 0) | 569 | if (length < 0) |
570 | goto out2; | 570 | goto out2; |
571 | 571 | ||
@@ -609,11 +609,11 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
609 | return length; | 609 | return length; |
610 | 610 | ||
611 | length = -ENOMEM; | 611 | length = -ENOMEM; |
612 | scon = kzalloc(size+1, GFP_KERNEL); | 612 | scon = kzalloc(size + 1, GFP_KERNEL); |
613 | if (!scon) | 613 | if (!scon) |
614 | return length; | 614 | return length; |
615 | 615 | ||
616 | tcon = kzalloc(size+1, GFP_KERNEL); | 616 | tcon = kzalloc(size + 1, GFP_KERNEL); |
617 | if (!tcon) | 617 | if (!tcon) |
618 | goto out; | 618 | goto out; |
619 | 619 | ||
@@ -621,10 +621,10 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
621 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 621 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
622 | goto out2; | 622 | goto out2; |
623 | 623 | ||
624 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 624 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
625 | if (length < 0) | 625 | if (length < 0) |
626 | goto out2; | 626 | goto out2; |
627 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 627 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
628 | if (length < 0) | 628 | if (length < 0) |
629 | goto out2; | 629 | goto out2; |
630 | 630 | ||
@@ -666,11 +666,11 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
666 | return length; | 666 | return length; |
667 | 667 | ||
668 | length = -ENOMEM; | 668 | length = -ENOMEM; |
669 | con = kzalloc(size+1, GFP_KERNEL); | 669 | con = kzalloc(size + 1, GFP_KERNEL); |
670 | if (!con) | 670 | if (!con) |
671 | return length; | 671 | return length; |
672 | 672 | ||
673 | user = kzalloc(size+1, GFP_KERNEL); | 673 | user = kzalloc(size + 1, GFP_KERNEL); |
674 | if (!user) | 674 | if (!user) |
675 | goto out; | 675 | goto out; |
676 | 676 | ||
@@ -678,7 +678,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
678 | if (sscanf(buf, "%s %s", con, user) != 2) | 678 | if (sscanf(buf, "%s %s", con, user) != 2) |
679 | goto out2; | 679 | goto out2; |
680 | 680 | ||
681 | length = security_context_to_sid(con, strlen(con)+1, &sid); | 681 | length = security_context_to_sid(con, strlen(con) + 1, &sid); |
682 | if (length < 0) | 682 | if (length < 0) |
683 | goto out2; | 683 | goto out2; |
684 | 684 | ||
@@ -727,11 +727,11 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
727 | return length; | 727 | return length; |
728 | 728 | ||
729 | length = -ENOMEM; | 729 | length = -ENOMEM; |
730 | scon = kzalloc(size+1, GFP_KERNEL); | 730 | scon = kzalloc(size + 1, GFP_KERNEL); |
731 | if (!scon) | 731 | if (!scon) |
732 | return length; | 732 | return length; |
733 | 733 | ||
734 | tcon = kzalloc(size+1, GFP_KERNEL); | 734 | tcon = kzalloc(size + 1, GFP_KERNEL); |
735 | if (!tcon) | 735 | if (!tcon) |
736 | goto out; | 736 | goto out; |
737 | 737 | ||
@@ -739,10 +739,10 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
739 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 739 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
740 | goto out2; | 740 | goto out2; |
741 | 741 | ||
742 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 742 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
743 | if (length < 0) | 743 | if (length < 0) |
744 | goto out2; | 744 | goto out2; |
745 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 745 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
746 | if (length < 0) | 746 | if (length < 0) |
747 | goto out2; | 747 | goto out2; |
748 | 748 | ||
@@ -1401,7 +1401,7 @@ static int sel_make_perm_files(char *objclass, int classvalue, | |||
1401 | } | 1401 | } |
1402 | inode->i_fop = &sel_perm_ops; | 1402 | inode->i_fop = &sel_perm_ops; |
1403 | /* i+1 since perm values are 1-indexed */ | 1403 | /* i+1 since perm values are 1-indexed */ |
1404 | inode->i_ino = sel_perm_to_ino(classvalue, i+1); | 1404 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
1405 | d_add(dentry, inode); | 1405 | d_add(dentry, inode); |
1406 | } | 1406 | } |
1407 | 1407 | ||
@@ -1489,7 +1489,7 @@ static int sel_make_classes(void) | |||
1489 | goto out; | 1489 | goto out; |
1490 | 1490 | ||
1491 | /* +2 since classes are 1-indexed */ | 1491 | /* +2 since classes are 1-indexed */ |
1492 | last_class_ino = sel_class_to_ino(nclasses+2); | 1492 | last_class_ino = sel_class_to_ino(nclasses + 2); |
1493 | 1493 | ||
1494 | for (i = 0; i < nclasses; i++) { | 1494 | for (i = 0; i < nclasses; i++) { |
1495 | struct dentry *class_name_dir; | 1495 | struct dentry *class_name_dir; |
@@ -1506,7 +1506,7 @@ static int sel_make_classes(void) | |||
1506 | goto out1; | 1506 | goto out1; |
1507 | 1507 | ||
1508 | /* i+1 since class values are 1-indexed */ | 1508 | /* i+1 since class values are 1-indexed */ |
1509 | rc = sel_make_class_dir_entries(classes[i], i+1, | 1509 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
1510 | class_name_dir); | 1510 | class_name_dir); |
1511 | if (rc) | 1511 | if (rc) |
1512 | goto out1; | 1512 | goto out1; |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 372b773f8210..b4eff7a60c50 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -255,7 +255,7 @@ int mls_context_to_sid(struct policydb *pol, | |||
255 | 255 | ||
256 | if (!pol->mls_enabled) { | 256 | if (!pol->mls_enabled) { |
257 | if (def_sid != SECSID_NULL && oldc) | 257 | if (def_sid != SECSID_NULL && oldc) |
258 | *scontext += strlen(*scontext)+1; | 258 | *scontext += strlen(*scontext) + 1; |
259 | return 0; | 259 | return 0; |
260 | } | 260 | } |
261 | 261 | ||
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 23c6e53c102c..c57802a164d5 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #define _DEBUG_HASHES | 40 | #define _DEBUG_HASHES |
41 | 41 | ||
42 | #ifdef DEBUG_HASHES | 42 | #ifdef DEBUG_HASHES |
43 | static char *symtab_name[SYM_NUM] = { | 43 | static const char *symtab_name[SYM_NUM] = { |
44 | "common prefixes", | 44 | "common prefixes", |
45 | "classes", | 45 | "classes", |
46 | "roles", | 46 | "roles", |
@@ -156,12 +156,11 @@ static int roles_init(struct policydb *p) | |||
156 | rc = -EINVAL; | 156 | rc = -EINVAL; |
157 | goto out_free_role; | 157 | goto out_free_role; |
158 | } | 158 | } |
159 | key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL); | 159 | key = kstrdup(OBJECT_R, GFP_KERNEL); |
160 | if (!key) { | 160 | if (!key) { |
161 | rc = -ENOMEM; | 161 | rc = -ENOMEM; |
162 | goto out_free_role; | 162 | goto out_free_role; |
163 | } | 163 | } |
164 | strcpy(key, OBJECT_R); | ||
165 | rc = hashtab_insert(p->p_roles.table, key, role); | 164 | rc = hashtab_insert(p->p_roles.table, key, role); |
166 | if (rc) | 165 | if (rc) |
167 | goto out_free_key; | 166 | goto out_free_key; |
@@ -2195,7 +2194,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
2195 | rangetr_hash_eval(p->range_tr); | 2194 | rangetr_hash_eval(p->range_tr); |
2196 | } | 2195 | } |
2197 | 2196 | ||
2198 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 2197 | p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); |
2199 | if (!p->type_attr_map) | 2198 | if (!p->type_attr_map) |
2200 | goto bad; | 2199 | goto bad; |
2201 | 2200 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index cf27b3ee1a95..1de60ce90d9a 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -274,15 +274,15 @@ static int constraint_expr_eval(struct context *scontext, | |||
274 | case CEXPR_AND: | 274 | case CEXPR_AND: |
275 | BUG_ON(sp < 1); | 275 | BUG_ON(sp < 1); |
276 | sp--; | 276 | sp--; |
277 | s[sp] &= s[sp+1]; | 277 | s[sp] &= s[sp + 1]; |
278 | break; | 278 | break; |
279 | case CEXPR_OR: | 279 | case CEXPR_OR: |
280 | BUG_ON(sp < 1); | 280 | BUG_ON(sp < 1); |
281 | sp--; | 281 | sp--; |
282 | s[sp] |= s[sp+1]; | 282 | s[sp] |= s[sp + 1]; |
283 | break; | 283 | break; |
284 | case CEXPR_ATTR: | 284 | case CEXPR_ATTR: |
285 | if (sp == (CEXPR_MAXDEPTH-1)) | 285 | if (sp == (CEXPR_MAXDEPTH - 1)) |
286 | return 0; | 286 | return 0; |
287 | switch (e->attr) { | 287 | switch (e->attr) { |
288 | case CEXPR_USER: | 288 | case CEXPR_USER: |
@@ -1216,7 +1216,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
1216 | *sid = SECSID_NULL; | 1216 | *sid = SECSID_NULL; |
1217 | 1217 | ||
1218 | /* Copy the string so that we can modify the copy as we parse it. */ | 1218 | /* Copy the string so that we can modify the copy as we parse it. */ |
1219 | scontext2 = kmalloc(scontext_len+1, gfp_flags); | 1219 | scontext2 = kmalloc(scontext_len + 1, gfp_flags); |
1220 | if (!scontext2) | 1220 | if (!scontext2) |
1221 | return -ENOMEM; | 1221 | return -ENOMEM; |
1222 | memcpy(scontext2, scontext, scontext_len); | 1222 | memcpy(scontext2, scontext, scontext_len); |
@@ -1760,22 +1760,28 @@ int security_load_policy(void *data, size_t len) | |||
1760 | 1760 | ||
1761 | if (!ss_initialized) { | 1761 | if (!ss_initialized) { |
1762 | avtab_cache_init(); | 1762 | avtab_cache_init(); |
1763 | if (policydb_read(&policydb, fp)) { | 1763 | rc = policydb_read(&policydb, fp); |
1764 | if (rc) { | ||
1764 | avtab_cache_destroy(); | 1765 | avtab_cache_destroy(); |
1765 | return -EINVAL; | 1766 | return rc; |
1766 | } | 1767 | } |
1767 | if (selinux_set_mapping(&policydb, secclass_map, | 1768 | |
1768 | ¤t_mapping, | 1769 | rc = selinux_set_mapping(&policydb, secclass_map, |
1769 | ¤t_mapping_size)) { | 1770 | ¤t_mapping, |
1771 | ¤t_mapping_size); | ||
1772 | if (rc) { | ||
1770 | policydb_destroy(&policydb); | 1773 | policydb_destroy(&policydb); |
1771 | avtab_cache_destroy(); | 1774 | avtab_cache_destroy(); |
1772 | return -EINVAL; | 1775 | return rc; |
1773 | } | 1776 | } |
1774 | if (policydb_load_isids(&policydb, &sidtab)) { | 1777 | |
1778 | rc = policydb_load_isids(&policydb, &sidtab); | ||
1779 | if (rc) { | ||
1775 | policydb_destroy(&policydb); | 1780 | policydb_destroy(&policydb); |
1776 | avtab_cache_destroy(); | 1781 | avtab_cache_destroy(); |
1777 | return -EINVAL; | 1782 | return rc; |
1778 | } | 1783 | } |
1784 | |||
1779 | security_load_policycaps(); | 1785 | security_load_policycaps(); |
1780 | ss_initialized = 1; | 1786 | ss_initialized = 1; |
1781 | seqno = ++latest_granting; | 1787 | seqno = ++latest_granting; |
@@ -1791,8 +1797,9 @@ int security_load_policy(void *data, size_t len) | |||
1791 | sidtab_hash_eval(&sidtab, "sids"); | 1797 | sidtab_hash_eval(&sidtab, "sids"); |
1792 | #endif | 1798 | #endif |
1793 | 1799 | ||
1794 | if (policydb_read(&newpolicydb, fp)) | 1800 | rc = policydb_read(&newpolicydb, fp); |
1795 | return -EINVAL; | 1801 | if (rc) |
1802 | return rc; | ||
1796 | 1803 | ||
1797 | /* If switching between different policy types, log MLS status */ | 1804 | /* If switching between different policy types, log MLS status */ |
1798 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | 1805 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) |
@@ -1807,8 +1814,8 @@ int security_load_policy(void *data, size_t len) | |||
1807 | return rc; | 1814 | return rc; |
1808 | } | 1815 | } |
1809 | 1816 | ||
1810 | if (selinux_set_mapping(&newpolicydb, secclass_map, | 1817 | rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); |
1811 | &map, &map_size)) | 1818 | if (rc) |
1812 | goto err; | 1819 | goto err; |
1813 | 1820 | ||
1814 | rc = security_preserve_bools(&newpolicydb); | 1821 | rc = security_preserve_bools(&newpolicydb); |
@@ -1819,10 +1826,10 @@ int security_load_policy(void *data, size_t len) | |||
1819 | 1826 | ||
1820 | /* Clone the SID table. */ | 1827 | /* Clone the SID table. */ |
1821 | sidtab_shutdown(&sidtab); | 1828 | sidtab_shutdown(&sidtab); |
1822 | if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { | 1829 | |
1823 | rc = -ENOMEM; | 1830 | rc = sidtab_map(&sidtab, clone_sid, &newsidtab); |
1831 | if (rc) | ||
1824 | goto err; | 1832 | goto err; |
1825 | } | ||
1826 | 1833 | ||
1827 | /* | 1834 | /* |
1828 | * Convert the internal representations of contexts | 1835 | * Convert the internal representations of contexts |
@@ -2101,9 +2108,9 @@ int security_get_user_sids(u32 fromsid, | |||
2101 | 2108 | ||
2102 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { | 2109 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
2103 | role = policydb.role_val_to_struct[i]; | 2110 | role = policydb.role_val_to_struct[i]; |
2104 | usercon.role = i+1; | 2111 | usercon.role = i + 1; |
2105 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { | 2112 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
2106 | usercon.type = j+1; | 2113 | usercon.type = j + 1; |
2107 | 2114 | ||
2108 | if (mls_setup_user_range(fromcon, user, &usercon)) | 2115 | if (mls_setup_user_range(fromcon, user, &usercon)) |
2109 | continue; | 2116 | continue; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index fdfeaa2f28ec..0f2fc480fc61 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
20 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
21 | #include <linux/stat.h> | 21 | #include <linux/stat.h> |
22 | #include <linux/ext2_fs.h> | ||
23 | #include <linux/kd.h> | 22 | #include <linux/kd.h> |
24 | #include <asm/ioctls.h> | 23 | #include <asm/ioctls.h> |
25 | #include <linux/ip.h> | 24 | #include <linux/ip.h> |
@@ -1119,15 +1118,6 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
1119 | } | 1118 | } |
1120 | 1119 | ||
1121 | /** | 1120 | /** |
1122 | * smack_cred_commit - commit new credentials | ||
1123 | * @new: the new credentials | ||
1124 | * @old: the original credentials | ||
1125 | */ | ||
1126 | static void smack_cred_commit(struct cred *new, const struct cred *old) | ||
1127 | { | ||
1128 | } | ||
1129 | |||
1130 | /** | ||
1131 | * smack_cred_transfer - Transfer the old credentials to the new credentials | 1121 | * smack_cred_transfer - Transfer the old credentials to the new credentials |
1132 | * @new: the new credentials | 1122 | * @new: the new credentials |
1133 | * @old: the original credentials | 1123 | * @old: the original credentials |
@@ -3121,7 +3111,6 @@ struct security_operations smack_ops = { | |||
3121 | .cred_alloc_blank = smack_cred_alloc_blank, | 3111 | .cred_alloc_blank = smack_cred_alloc_blank, |
3122 | .cred_free = smack_cred_free, | 3112 | .cred_free = smack_cred_free, |
3123 | .cred_prepare = smack_cred_prepare, | 3113 | .cred_prepare = smack_cred_prepare, |
3124 | .cred_commit = smack_cred_commit, | ||
3125 | .cred_transfer = smack_cred_transfer, | 3114 | .cred_transfer = smack_cred_transfer, |
3126 | .kernel_act_as = smack_kernel_act_as, | 3115 | .kernel_act_as = smack_kernel_act_as, |
3127 | .kernel_create_files_as = smack_kernel_create_files_as, | 3116 | .kernel_create_files_as = smack_kernel_create_files_as, |
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 60a9e2002da1..4fb39030f6bd 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1 +1 @@ | |||
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o | obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 975c45d88baa..b5dbdc9ff73c 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -76,6 +76,49 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
76 | const int buffer_len); | 76 | const int buffer_len); |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * tomoyo_parse_name_union - Parse a tomoyo_name_union. | ||
80 | * | ||
81 | * @filename: Name or name group. | ||
82 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
83 | * | ||
84 | * Returns true on success, false otherwise. | ||
85 | */ | ||
86 | bool tomoyo_parse_name_union(const char *filename, | ||
87 | struct tomoyo_name_union *ptr) | ||
88 | { | ||
89 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) | ||
90 | return false; | ||
91 | if (filename[0] == '@') { | ||
92 | ptr->group = tomoyo_get_path_group(filename + 1); | ||
93 | ptr->is_group = true; | ||
94 | return ptr->group != NULL; | ||
95 | } | ||
96 | ptr->filename = tomoyo_get_name(filename); | ||
97 | ptr->is_group = false; | ||
98 | return ptr->filename != NULL; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * tomoyo_print_name_union - Print a tomoyo_name_union. | ||
103 | * | ||
104 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
105 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
106 | * | ||
107 | * Returns true on success, false otherwise. | ||
108 | */ | ||
109 | static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, | ||
110 | const struct tomoyo_name_union *ptr) | ||
111 | { | ||
112 | int pos = head->read_avail; | ||
113 | if (pos && head->read_buf[pos - 1] == ' ') | ||
114 | head->read_avail--; | ||
115 | if (ptr->is_group) | ||
116 | return tomoyo_io_printf(head, " @%s", | ||
117 | ptr->group->group_name->name); | ||
118 | return tomoyo_io_printf(head, " %s", ptr->filename->name); | ||
119 | } | ||
120 | |||
121 | /** | ||
79 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. | 122 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. |
80 | * | 123 | * |
81 | * @str: Pointer to the string. | 124 | * @str: Pointer to the string. |
@@ -172,6 +215,33 @@ static void tomoyo_normalize_line(unsigned char *buffer) | |||
172 | } | 215 | } |
173 | 216 | ||
174 | /** | 217 | /** |
218 | * tomoyo_tokenize - Tokenize string. | ||
219 | * | ||
220 | * @buffer: The line to tokenize. | ||
221 | * @w: Pointer to "char *". | ||
222 | * @size: Sizeof @w . | ||
223 | * | ||
224 | * Returns true on success, false otherwise. | ||
225 | */ | ||
226 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size) | ||
227 | { | ||
228 | int count = size / sizeof(char *); | ||
229 | int i; | ||
230 | for (i = 0; i < count; i++) | ||
231 | w[i] = ""; | ||
232 | for (i = 0; i < count; i++) { | ||
233 | char *cp = strchr(buffer, ' '); | ||
234 | if (cp) | ||
235 | *cp = '\0'; | ||
236 | w[i] = buffer; | ||
237 | if (!cp) | ||
238 | break; | ||
239 | buffer = cp + 1; | ||
240 | } | ||
241 | return i < count || !*buffer; | ||
242 | } | ||
243 | |||
244 | /** | ||
175 | * tomoyo_is_correct_path - Validate a pathname. | 245 | * tomoyo_is_correct_path - Validate a pathname. |
176 | * @filename: The pathname to check. | 246 | * @filename: The pathname to check. |
177 | * @start_type: Should the pathname start with '/'? | 247 | * @start_type: Should the pathname start with '/'? |
@@ -874,17 +944,17 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | |||
874 | static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | 944 | static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned |
875 | int profile) | 945 | int profile) |
876 | { | 946 | { |
877 | static DEFINE_MUTEX(lock); | ||
878 | struct tomoyo_profile *ptr = NULL; | 947 | struct tomoyo_profile *ptr = NULL; |
879 | int i; | 948 | int i; |
880 | 949 | ||
881 | if (profile >= TOMOYO_MAX_PROFILES) | 950 | if (profile >= TOMOYO_MAX_PROFILES) |
882 | return NULL; | 951 | return NULL; |
883 | mutex_lock(&lock); | 952 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
953 | return NULL; | ||
884 | ptr = tomoyo_profile_ptr[profile]; | 954 | ptr = tomoyo_profile_ptr[profile]; |
885 | if (ptr) | 955 | if (ptr) |
886 | goto ok; | 956 | goto ok; |
887 | ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); | 957 | ptr = kmalloc(sizeof(*ptr), GFP_NOFS); |
888 | if (!tomoyo_memory_ok(ptr)) { | 958 | if (!tomoyo_memory_ok(ptr)) { |
889 | kfree(ptr); | 959 | kfree(ptr); |
890 | ptr = NULL; | 960 | ptr = NULL; |
@@ -895,7 +965,7 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | |||
895 | mb(); /* Avoid out-of-order execution. */ | 965 | mb(); /* Avoid out-of-order execution. */ |
896 | tomoyo_profile_ptr[profile] = ptr; | 966 | tomoyo_profile_ptr[profile] = ptr; |
897 | ok: | 967 | ok: |
898 | mutex_unlock(&lock); | 968 | mutex_unlock(&tomoyo_policy_lock); |
899 | return ptr; | 969 | return ptr; |
900 | } | 970 | } |
901 | 971 | ||
@@ -1071,44 +1141,42 @@ LIST_HEAD(tomoyo_policy_manager_list); | |||
1071 | static int tomoyo_update_manager_entry(const char *manager, | 1141 | static int tomoyo_update_manager_entry(const char *manager, |
1072 | const bool is_delete) | 1142 | const bool is_delete) |
1073 | { | 1143 | { |
1074 | struct tomoyo_policy_manager_entry *entry = NULL; | ||
1075 | struct tomoyo_policy_manager_entry *ptr; | 1144 | struct tomoyo_policy_manager_entry *ptr; |
1076 | const struct tomoyo_path_info *saved_manager; | 1145 | struct tomoyo_policy_manager_entry e = { }; |
1077 | int error = is_delete ? -ENOENT : -ENOMEM; | 1146 | int error = is_delete ? -ENOENT : -ENOMEM; |
1078 | bool is_domain = false; | ||
1079 | 1147 | ||
1080 | if (tomoyo_is_domain_def(manager)) { | 1148 | if (tomoyo_is_domain_def(manager)) { |
1081 | if (!tomoyo_is_correct_domain(manager)) | 1149 | if (!tomoyo_is_correct_domain(manager)) |
1082 | return -EINVAL; | 1150 | return -EINVAL; |
1083 | is_domain = true; | 1151 | e.is_domain = true; |
1084 | } else { | 1152 | } else { |
1085 | if (!tomoyo_is_correct_path(manager, 1, -1, -1)) | 1153 | if (!tomoyo_is_correct_path(manager, 1, -1, -1)) |
1086 | return -EINVAL; | 1154 | return -EINVAL; |
1087 | } | 1155 | } |
1088 | saved_manager = tomoyo_get_name(manager); | 1156 | e.manager = tomoyo_get_name(manager); |
1089 | if (!saved_manager) | 1157 | if (!e.manager) |
1090 | return -ENOMEM; | 1158 | return -ENOMEM; |
1091 | if (!is_delete) | 1159 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
1092 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 1160 | goto out; |
1093 | mutex_lock(&tomoyo_policy_lock); | ||
1094 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { | 1161 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1095 | if (ptr->manager != saved_manager) | 1162 | if (ptr->manager != e.manager) |
1096 | continue; | 1163 | continue; |
1097 | ptr->is_deleted = is_delete; | 1164 | ptr->is_deleted = is_delete; |
1098 | error = 0; | 1165 | error = 0; |
1099 | break; | 1166 | break; |
1100 | } | 1167 | } |
1101 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 1168 | if (!is_delete && error) { |
1102 | entry->manager = saved_manager; | 1169 | struct tomoyo_policy_manager_entry *entry = |
1103 | saved_manager = NULL; | 1170 | tomoyo_commit_ok(&e, sizeof(e)); |
1104 | entry->is_domain = is_domain; | 1171 | if (entry) { |
1105 | list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); | 1172 | list_add_tail_rcu(&entry->list, |
1106 | entry = NULL; | 1173 | &tomoyo_policy_manager_list); |
1107 | error = 0; | 1174 | error = 0; |
1175 | } | ||
1108 | } | 1176 | } |
1109 | mutex_unlock(&tomoyo_policy_lock); | 1177 | mutex_unlock(&tomoyo_policy_lock); |
1110 | tomoyo_put_name(saved_manager); | 1178 | out: |
1111 | kfree(entry); | 1179 | tomoyo_put_name(e.manager); |
1112 | return error; | 1180 | return error; |
1113 | } | 1181 | } |
1114 | 1182 | ||
@@ -1287,7 +1355,8 @@ static int tomoyo_delete_domain(char *domainname) | |||
1287 | 1355 | ||
1288 | name.name = domainname; | 1356 | name.name = domainname; |
1289 | tomoyo_fill_path_info(&name); | 1357 | tomoyo_fill_path_info(&name); |
1290 | mutex_lock(&tomoyo_policy_lock); | 1358 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
1359 | return 0; | ||
1291 | /* Is there an active domain? */ | 1360 | /* Is there an active domain? */ |
1292 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 1361 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
1293 | /* Never delete tomoyo_kernel_domain */ | 1362 | /* Never delete tomoyo_kernel_domain */ |
@@ -1369,23 +1438,20 @@ static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, | |||
1369 | { | 1438 | { |
1370 | int pos; | 1439 | int pos; |
1371 | u8 bit; | 1440 | u8 bit; |
1372 | const char *atmark = ""; | ||
1373 | const char *filename; | ||
1374 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); | 1441 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); |
1375 | 1442 | ||
1376 | filename = ptr->filename->name; | ||
1377 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { | 1443 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
1378 | const char *msg; | ||
1379 | if (!(perm & (1 << bit))) | 1444 | if (!(perm & (1 << bit))) |
1380 | continue; | 1445 | continue; |
1381 | /* Print "read/write" instead of "read" and "write". */ | 1446 | /* Print "read/write" instead of "read" and "write". */ |
1382 | if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) | 1447 | if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) |
1383 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) | 1448 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
1384 | continue; | 1449 | continue; |
1385 | msg = tomoyo_path2keyword(bit); | ||
1386 | pos = head->read_avail; | 1450 | pos = head->read_avail; |
1387 | if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, | 1451 | if (!tomoyo_io_printf(head, "allow_%s ", |
1388 | atmark, filename)) | 1452 | tomoyo_path2keyword(bit)) || |
1453 | !tomoyo_print_name_union(head, &ptr->name) || | ||
1454 | !tomoyo_io_printf(head, "\n")) | ||
1389 | goto out; | 1455 | goto out; |
1390 | } | 1456 | } |
1391 | head->read_bit = 0; | 1457 | head->read_bit = 0; |
@@ -1408,23 +1474,18 @@ static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, | |||
1408 | struct tomoyo_path2_acl *ptr) | 1474 | struct tomoyo_path2_acl *ptr) |
1409 | { | 1475 | { |
1410 | int pos; | 1476 | int pos; |
1411 | const char *atmark1 = ""; | ||
1412 | const char *atmark2 = ""; | ||
1413 | const char *filename1; | ||
1414 | const char *filename2; | ||
1415 | const u8 perm = ptr->perm; | 1477 | const u8 perm = ptr->perm; |
1416 | u8 bit; | 1478 | u8 bit; |
1417 | 1479 | ||
1418 | filename1 = ptr->filename1->name; | ||
1419 | filename2 = ptr->filename2->name; | ||
1420 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { | 1480 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { |
1421 | const char *msg; | ||
1422 | if (!(perm & (1 << bit))) | 1481 | if (!(perm & (1 << bit))) |
1423 | continue; | 1482 | continue; |
1424 | msg = tomoyo_path22keyword(bit); | ||
1425 | pos = head->read_avail; | 1483 | pos = head->read_avail; |
1426 | if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, | 1484 | if (!tomoyo_io_printf(head, "allow_%s ", |
1427 | atmark1, filename1, atmark2, filename2)) | 1485 | tomoyo_path22keyword(bit)) || |
1486 | !tomoyo_print_name_union(head, &ptr->name1) || | ||
1487 | !tomoyo_print_name_union(head, &ptr->name2) || | ||
1488 | !tomoyo_io_printf(head, "\n")) | ||
1428 | goto out; | 1489 | goto out; |
1429 | } | 1490 | } |
1430 | head->read_bit = 0; | 1491 | head->read_bit = 0; |
@@ -1687,6 +1748,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1687 | return tomoyo_write_pattern_policy(data, is_delete); | 1748 | return tomoyo_write_pattern_policy(data, is_delete); |
1688 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) | 1749 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) |
1689 | return tomoyo_write_no_rewrite_policy(data, is_delete); | 1750 | return tomoyo_write_no_rewrite_policy(data, is_delete); |
1751 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) | ||
1752 | return tomoyo_write_path_group_policy(data, is_delete); | ||
1690 | return -EINVAL; | 1753 | return -EINVAL; |
1691 | } | 1754 | } |
1692 | 1755 | ||
@@ -1743,6 +1806,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | |||
1743 | head->read_var2 = NULL; | 1806 | head->read_var2 = NULL; |
1744 | head->read_step = 9; | 1807 | head->read_step = 9; |
1745 | case 9: | 1808 | case 9: |
1809 | if (!tomoyo_read_path_group_policy(head)) | ||
1810 | break; | ||
1811 | head->read_var1 = NULL; | ||
1812 | head->read_var2 = NULL; | ||
1813 | head->read_step = 10; | ||
1814 | case 10: | ||
1746 | head->read_eof = true; | 1815 | head->read_eof = true; |
1747 | break; | 1816 | break; |
1748 | default: | 1817 | default: |
@@ -1886,7 +1955,7 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) | |||
1886 | */ | 1955 | */ |
1887 | static int tomoyo_open_control(const u8 type, struct file *file) | 1956 | static int tomoyo_open_control(const u8 type, struct file *file) |
1888 | { | 1957 | { |
1889 | struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL); | 1958 | struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); |
1890 | 1959 | ||
1891 | if (!head) | 1960 | if (!head) |
1892 | return -ENOMEM; | 1961 | return -ENOMEM; |
@@ -1947,7 +2016,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
1947 | } else { | 2016 | } else { |
1948 | if (!head->readbuf_size) | 2017 | if (!head->readbuf_size) |
1949 | head->readbuf_size = 4096 * 2; | 2018 | head->readbuf_size = 4096 * 2; |
1950 | head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL); | 2019 | head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); |
1951 | if (!head->read_buf) { | 2020 | if (!head->read_buf) { |
1952 | kfree(head); | 2021 | kfree(head); |
1953 | return -ENOMEM; | 2022 | return -ENOMEM; |
@@ -1961,7 +2030,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
1961 | head->write = NULL; | 2030 | head->write = NULL; |
1962 | } else if (head->write) { | 2031 | } else if (head->write) { |
1963 | head->writebuf_size = 4096 * 2; | 2032 | head->writebuf_size = 4096 * 2; |
1964 | head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL); | 2033 | head->write_buf = kzalloc(head->writebuf_size, GFP_NOFS); |
1965 | if (!head->write_buf) { | 2034 | if (!head->write_buf) { |
1966 | kfree(head->read_buf); | 2035 | kfree(head->read_buf); |
1967 | kfree(head); | 2036 | kfree(head); |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 67bd22dd3e68..9f1ae5e3ba51 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -54,6 +54,7 @@ struct linux_binprm; | |||
54 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | 54 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " |
55 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | 55 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " |
56 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " | 56 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " |
57 | #define TOMOYO_KEYWORD_PATH_GROUP "path_group " | ||
57 | #define TOMOYO_KEYWORD_SELECT "select " | 58 | #define TOMOYO_KEYWORD_SELECT "select " |
58 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | 59 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " |
59 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | 60 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" |
@@ -204,6 +205,27 @@ struct tomoyo_path_info_with_data { | |||
204 | char barrier2[16]; /* Safeguard for overrun. */ | 205 | char barrier2[16]; /* Safeguard for overrun. */ |
205 | }; | 206 | }; |
206 | 207 | ||
208 | struct tomoyo_name_union { | ||
209 | const struct tomoyo_path_info *filename; | ||
210 | struct tomoyo_path_group *group; | ||
211 | u8 is_group; | ||
212 | }; | ||
213 | |||
214 | /* Structure for "path_group" directive. */ | ||
215 | struct tomoyo_path_group { | ||
216 | struct list_head list; | ||
217 | const struct tomoyo_path_info *group_name; | ||
218 | struct list_head member_list; | ||
219 | atomic_t users; | ||
220 | }; | ||
221 | |||
222 | /* Structure for "path_group" directive. */ | ||
223 | struct tomoyo_path_group_member { | ||
224 | struct list_head list; | ||
225 | bool is_deleted; | ||
226 | const struct tomoyo_path_info *member_name; | ||
227 | }; | ||
228 | |||
207 | /* | 229 | /* |
208 | * tomoyo_acl_info is a structure which is used for holding | 230 | * tomoyo_acl_info is a structure which is used for holding |
209 | * | 231 | * |
@@ -274,7 +296,7 @@ struct tomoyo_domain_info { | |||
274 | * | 296 | * |
275 | * (1) "head" which is a "struct tomoyo_acl_info". | 297 | * (1) "head" which is a "struct tomoyo_acl_info". |
276 | * (2) "perm" which is a bitmask of permitted operations. | 298 | * (2) "perm" which is a bitmask of permitted operations. |
277 | * (3) "filename" is the pathname. | 299 | * (3) "name" is the pathname. |
278 | * | 300 | * |
279 | * Directives held by this structure are "allow_read/write", "allow_execute", | 301 | * Directives held by this structure are "allow_read/write", "allow_execute", |
280 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", | 302 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", |
@@ -287,8 +309,7 @@ struct tomoyo_path_acl { | |||
287 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 309 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
288 | u8 perm_high; | 310 | u8 perm_high; |
289 | u16 perm; | 311 | u16 perm; |
290 | /* Pointer to single pathname. */ | 312 | struct tomoyo_name_union name; |
291 | const struct tomoyo_path_info *filename; | ||
292 | }; | 313 | }; |
293 | 314 | ||
294 | /* | 315 | /* |
@@ -298,8 +319,8 @@ struct tomoyo_path_acl { | |||
298 | * | 319 | * |
299 | * (1) "head" which is a "struct tomoyo_acl_info". | 320 | * (1) "head" which is a "struct tomoyo_acl_info". |
300 | * (2) "perm" which is a bitmask of permitted operations. | 321 | * (2) "perm" which is a bitmask of permitted operations. |
301 | * (3) "filename1" is the source/old pathname. | 322 | * (3) "name1" is the source/old pathname. |
302 | * (4) "filename2" is the destination/new pathname. | 323 | * (4) "name2" is the destination/new pathname. |
303 | * | 324 | * |
304 | * Directives held by this structure are "allow_rename", "allow_link" and | 325 | * Directives held by this structure are "allow_rename", "allow_link" and |
305 | * "allow_pivot_root". | 326 | * "allow_pivot_root". |
@@ -307,10 +328,8 @@ struct tomoyo_path_acl { | |||
307 | struct tomoyo_path2_acl { | 328 | struct tomoyo_path2_acl { |
308 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ | 329 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ |
309 | u8 perm; | 330 | u8 perm; |
310 | /* Pointer to single pathname. */ | 331 | struct tomoyo_name_union name1; |
311 | const struct tomoyo_path_info *filename1; | 332 | struct tomoyo_name_union name2; |
312 | /* Pointer to single pathname. */ | ||
313 | const struct tomoyo_path_info *filename2; | ||
314 | }; | 333 | }; |
315 | 334 | ||
316 | /* | 335 | /* |
@@ -514,6 +533,9 @@ struct tomoyo_policy_manager_entry { | |||
514 | 533 | ||
515 | /********** Function prototypes. **********/ | 534 | /********** Function prototypes. **********/ |
516 | 535 | ||
536 | /* Check whether the given name matches the given name_union. */ | ||
537 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | ||
538 | const struct tomoyo_name_union *ptr); | ||
517 | /* Check whether the domain has too many ACL entries to hold. */ | 539 | /* Check whether the domain has too many ACL entries to hold. */ |
518 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); | 540 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); |
519 | /* Transactional sprintf() for policy dump. */ | 541 | /* Transactional sprintf() for policy dump. */ |
@@ -526,6 +548,12 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
526 | const s8 pattern_type, const s8 end_type); | 548 | const s8 pattern_type, const s8 end_type); |
527 | /* Check whether the token can be a domainname. */ | 549 | /* Check whether the token can be a domainname. */ |
528 | bool tomoyo_is_domain_def(const unsigned char *buffer); | 550 | bool tomoyo_is_domain_def(const unsigned char *buffer); |
551 | bool tomoyo_parse_name_union(const char *filename, | ||
552 | struct tomoyo_name_union *ptr); | ||
553 | /* Check whether the given filename matches the given path_group. */ | ||
554 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | ||
555 | const struct tomoyo_path_group *group, | ||
556 | const bool may_use_pattern); | ||
529 | /* Check whether the given filename matches the given pattern. */ | 557 | /* Check whether the given filename matches the given pattern. */ |
530 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 558 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
531 | const struct tomoyo_path_info *pattern); | 559 | const struct tomoyo_path_info *pattern); |
@@ -540,10 +568,14 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head); | |||
540 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); | 568 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); |
541 | /* Read "file_pattern" entry in exception policy. */ | 569 | /* Read "file_pattern" entry in exception policy. */ |
542 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); | 570 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); |
571 | /* Read "path_group" entry in exception policy. */ | ||
572 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); | ||
543 | /* Read "allow_read" entry in exception policy. */ | 573 | /* Read "allow_read" entry in exception policy. */ |
544 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); | 574 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); |
545 | /* Read "deny_rewrite" entry in exception policy. */ | 575 | /* Read "deny_rewrite" entry in exception policy. */ |
546 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); | 576 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); |
577 | /* Tokenize a line. */ | ||
578 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size); | ||
547 | /* Write domain policy violation warning message to console? */ | 579 | /* Write domain policy violation warning message to console? */ |
548 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | 580 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); |
549 | /* Convert double path operation to operation name. */ | 581 | /* Convert double path operation to operation name. */ |
@@ -580,12 +612,18 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); | |||
580 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); | 612 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); |
581 | /* Create "file_pattern" entry in exception policy. */ | 613 | /* Create "file_pattern" entry in exception policy. */ |
582 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); | 614 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); |
615 | /* Create "path_group" entry in exception policy. */ | ||
616 | int tomoyo_write_path_group_policy(char *data, const bool is_delete); | ||
583 | /* Find a domain by the given name. */ | 617 | /* Find a domain by the given name. */ |
584 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 618 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
585 | /* Find or create a domain by the given name. */ | 619 | /* Find or create a domain by the given name. */ |
586 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 620 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
587 | domainname, | 621 | domainname, |
588 | const u8 profile); | 622 | const u8 profile); |
623 | |||
624 | /* Allocate memory for "struct tomoyo_path_group". */ | ||
625 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); | ||
626 | |||
589 | /* Check mode for specified functionality. */ | 627 | /* Check mode for specified functionality. */ |
590 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 628 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
591 | const u8 index); | 629 | const u8 index); |
@@ -616,6 +654,7 @@ char *tomoyo_realpath_from_path(struct path *path); | |||
616 | 654 | ||
617 | /* Check memory quota. */ | 655 | /* Check memory quota. */ |
618 | bool tomoyo_memory_ok(void *ptr); | 656 | bool tomoyo_memory_ok(void *ptr); |
657 | void *tomoyo_commit_ok(void *data, const unsigned int size); | ||
619 | 658 | ||
620 | /* | 659 | /* |
621 | * Keep the given name on the RAM. | 660 | * Keep the given name on the RAM. |
@@ -641,6 +680,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
641 | int tomoyo_check_rewrite_permission(struct file *filp); | 680 | int tomoyo_check_rewrite_permission(struct file *filp); |
642 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 681 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
643 | 682 | ||
683 | /* Drop refcount on tomoyo_name_union. */ | ||
684 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | ||
685 | |||
644 | /* Run garbage collector. */ | 686 | /* Run garbage collector. */ |
645 | void tomoyo_run_gc(void); | 687 | void tomoyo_run_gc(void); |
646 | 688 | ||
@@ -654,6 +696,7 @@ extern struct srcu_struct tomoyo_ss; | |||
654 | /* The list for "struct tomoyo_domain_info". */ | 696 | /* The list for "struct tomoyo_domain_info". */ |
655 | extern struct list_head tomoyo_domain_list; | 697 | extern struct list_head tomoyo_domain_list; |
656 | 698 | ||
699 | extern struct list_head tomoyo_path_group_list; | ||
657 | extern struct list_head tomoyo_domain_initializer_list; | 700 | extern struct list_head tomoyo_domain_initializer_list; |
658 | extern struct list_head tomoyo_domain_keeper_list; | 701 | extern struct list_head tomoyo_domain_keeper_list; |
659 | extern struct list_head tomoyo_alias_list; | 702 | extern struct list_head tomoyo_alias_list; |
@@ -662,7 +705,6 @@ extern struct list_head tomoyo_pattern_list; | |||
662 | extern struct list_head tomoyo_no_rewrite_list; | 705 | extern struct list_head tomoyo_no_rewrite_list; |
663 | extern struct list_head tomoyo_policy_manager_list; | 706 | extern struct list_head tomoyo_policy_manager_list; |
664 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 707 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
665 | extern struct mutex tomoyo_name_list_lock; | ||
666 | 708 | ||
667 | /* Lock for protecting policy. */ | 709 | /* Lock for protecting policy. */ |
668 | extern struct mutex tomoyo_policy_lock; | 710 | extern struct mutex tomoyo_policy_lock; |
@@ -725,6 +767,12 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | |||
725 | } | 767 | } |
726 | } | 768 | } |
727 | 769 | ||
770 | static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) | ||
771 | { | ||
772 | if (group) | ||
773 | atomic_dec(&group->users); | ||
774 | } | ||
775 | |||
728 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | 776 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
729 | { | 777 | { |
730 | return current_cred()->security; | 778 | return current_cred()->security; |
@@ -736,6 +784,59 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | |||
736 | return task_cred_xxx(task, security); | 784 | return task_cred_xxx(task, security); |
737 | } | 785 | } |
738 | 786 | ||
787 | static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, | ||
788 | const struct tomoyo_acl_info *p2) | ||
789 | { | ||
790 | return p1->type == p2->type; | ||
791 | } | ||
792 | |||
793 | static inline bool tomoyo_is_same_name_union | ||
794 | (const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) | ||
795 | { | ||
796 | return p1->filename == p2->filename && p1->group == p2->group && | ||
797 | p1->is_group == p2->is_group; | ||
798 | } | ||
799 | |||
800 | static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, | ||
801 | const struct tomoyo_path_acl *p2) | ||
802 | { | ||
803 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) && | ||
804 | tomoyo_is_same_name_union(&p1->name, &p2->name); | ||
805 | } | ||
806 | |||
807 | static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, | ||
808 | const struct tomoyo_path2_acl *p2) | ||
809 | { | ||
810 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) && | ||
811 | tomoyo_is_same_name_union(&p1->name1, &p2->name1) && | ||
812 | tomoyo_is_same_name_union(&p1->name2, &p2->name2); | ||
813 | } | ||
814 | |||
815 | static inline bool tomoyo_is_same_domain_initializer_entry | ||
816 | (const struct tomoyo_domain_initializer_entry *p1, | ||
817 | const struct tomoyo_domain_initializer_entry *p2) | ||
818 | { | ||
819 | return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name | ||
820 | && p1->domainname == p2->domainname | ||
821 | && p1->program == p2->program; | ||
822 | } | ||
823 | |||
824 | static inline bool tomoyo_is_same_domain_keeper_entry | ||
825 | (const struct tomoyo_domain_keeper_entry *p1, | ||
826 | const struct tomoyo_domain_keeper_entry *p2) | ||
827 | { | ||
828 | return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name | ||
829 | && p1->domainname == p2->domainname | ||
830 | && p1->program == p2->program; | ||
831 | } | ||
832 | |||
833 | static inline bool tomoyo_is_same_alias_entry | ||
834 | (const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2) | ||
835 | { | ||
836 | return p1->original_name == p2->original_name && | ||
837 | p1->aliased_name == p2->aliased_name; | ||
838 | } | ||
839 | |||
739 | /** | 840 | /** |
740 | * list_for_each_cookie - iterate over a list with cookie. | 841 | * list_for_each_cookie - iterate over a list with cookie. |
741 | * @pos: the &struct list_head to use as a loop cursor. | 842 | * @pos: the &struct list_head to use as a loop cursor. |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index acb8c397d5cf..cd8ba4446763 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -130,57 +130,47 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
130 | const bool is_not, | 130 | const bool is_not, |
131 | const bool is_delete) | 131 | const bool is_delete) |
132 | { | 132 | { |
133 | struct tomoyo_domain_initializer_entry *entry = NULL; | ||
134 | struct tomoyo_domain_initializer_entry *ptr; | 133 | struct tomoyo_domain_initializer_entry *ptr; |
135 | const struct tomoyo_path_info *saved_program = NULL; | 134 | struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; |
136 | const struct tomoyo_path_info *saved_domainname = NULL; | ||
137 | int error = is_delete ? -ENOENT : -ENOMEM; | 135 | int error = is_delete ? -ENOENT : -ENOMEM; |
138 | bool is_last_name = false; | ||
139 | 136 | ||
140 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) | 137 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) |
141 | return -EINVAL; /* No patterns allowed. */ | 138 | return -EINVAL; /* No patterns allowed. */ |
142 | if (domainname) { | 139 | if (domainname) { |
143 | if (!tomoyo_is_domain_def(domainname) && | 140 | if (!tomoyo_is_domain_def(domainname) && |
144 | tomoyo_is_correct_path(domainname, 1, -1, -1)) | 141 | tomoyo_is_correct_path(domainname, 1, -1, -1)) |
145 | is_last_name = true; | 142 | e.is_last_name = true; |
146 | else if (!tomoyo_is_correct_domain(domainname)) | 143 | else if (!tomoyo_is_correct_domain(domainname)) |
147 | return -EINVAL; | 144 | return -EINVAL; |
148 | saved_domainname = tomoyo_get_name(domainname); | 145 | e.domainname = tomoyo_get_name(domainname); |
149 | if (!saved_domainname) | 146 | if (!e.domainname) |
150 | goto out; | 147 | goto out; |
151 | } | 148 | } |
152 | saved_program = tomoyo_get_name(program); | 149 | e.program = tomoyo_get_name(program); |
153 | if (!saved_program) | 150 | if (!e.program) |
151 | goto out; | ||
152 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
154 | goto out; | 153 | goto out; |
155 | if (!is_delete) | ||
156 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
157 | mutex_lock(&tomoyo_policy_lock); | ||
158 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { | 154 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
159 | if (ptr->is_not != is_not || | 155 | if (!tomoyo_is_same_domain_initializer_entry(ptr, &e)) |
160 | ptr->domainname != saved_domainname || | ||
161 | ptr->program != saved_program) | ||
162 | continue; | 156 | continue; |
163 | ptr->is_deleted = is_delete; | 157 | ptr->is_deleted = is_delete; |
164 | error = 0; | 158 | error = 0; |
165 | break; | 159 | break; |
166 | } | 160 | } |
167 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 161 | if (!is_delete && error) { |
168 | entry->domainname = saved_domainname; | 162 | struct tomoyo_domain_initializer_entry *entry = |
169 | saved_domainname = NULL; | 163 | tomoyo_commit_ok(&e, sizeof(e)); |
170 | entry->program = saved_program; | 164 | if (entry) { |
171 | saved_program = NULL; | 165 | list_add_tail_rcu(&entry->list, |
172 | entry->is_not = is_not; | 166 | &tomoyo_domain_initializer_list); |
173 | entry->is_last_name = is_last_name; | 167 | error = 0; |
174 | list_add_tail_rcu(&entry->list, | 168 | } |
175 | &tomoyo_domain_initializer_list); | ||
176 | entry = NULL; | ||
177 | error = 0; | ||
178 | } | 169 | } |
179 | mutex_unlock(&tomoyo_policy_lock); | 170 | mutex_unlock(&tomoyo_policy_lock); |
180 | out: | 171 | out: |
181 | tomoyo_put_name(saved_domainname); | 172 | tomoyo_put_name(e.domainname); |
182 | tomoyo_put_name(saved_program); | 173 | tomoyo_put_name(e.program); |
183 | kfree(entry); | ||
184 | return error; | 174 | return error; |
185 | } | 175 | } |
186 | 176 | ||
@@ -350,56 +340,47 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
350 | const bool is_not, | 340 | const bool is_not, |
351 | const bool is_delete) | 341 | const bool is_delete) |
352 | { | 342 | { |
353 | struct tomoyo_domain_keeper_entry *entry = NULL; | ||
354 | struct tomoyo_domain_keeper_entry *ptr; | 343 | struct tomoyo_domain_keeper_entry *ptr; |
355 | const struct tomoyo_path_info *saved_domainname = NULL; | 344 | struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; |
356 | const struct tomoyo_path_info *saved_program = NULL; | ||
357 | int error = is_delete ? -ENOENT : -ENOMEM; | 345 | int error = is_delete ? -ENOENT : -ENOMEM; |
358 | bool is_last_name = false; | ||
359 | 346 | ||
360 | if (!tomoyo_is_domain_def(domainname) && | 347 | if (!tomoyo_is_domain_def(domainname) && |
361 | tomoyo_is_correct_path(domainname, 1, -1, -1)) | 348 | tomoyo_is_correct_path(domainname, 1, -1, -1)) |
362 | is_last_name = true; | 349 | e.is_last_name = true; |
363 | else if (!tomoyo_is_correct_domain(domainname)) | 350 | else if (!tomoyo_is_correct_domain(domainname)) |
364 | return -EINVAL; | 351 | return -EINVAL; |
365 | if (program) { | 352 | if (program) { |
366 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) | 353 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) |
367 | return -EINVAL; | 354 | return -EINVAL; |
368 | saved_program = tomoyo_get_name(program); | 355 | e.program = tomoyo_get_name(program); |
369 | if (!saved_program) | 356 | if (!e.program) |
370 | goto out; | 357 | goto out; |
371 | } | 358 | } |
372 | saved_domainname = tomoyo_get_name(domainname); | 359 | e.domainname = tomoyo_get_name(domainname); |
373 | if (!saved_domainname) | 360 | if (!e.domainname) |
361 | goto out; | ||
362 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
374 | goto out; | 363 | goto out; |
375 | if (!is_delete) | ||
376 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
377 | mutex_lock(&tomoyo_policy_lock); | ||
378 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { | 364 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
379 | if (ptr->is_not != is_not || | 365 | if (!tomoyo_is_same_domain_keeper_entry(ptr, &e)) |
380 | ptr->domainname != saved_domainname || | ||
381 | ptr->program != saved_program) | ||
382 | continue; | 366 | continue; |
383 | ptr->is_deleted = is_delete; | 367 | ptr->is_deleted = is_delete; |
384 | error = 0; | 368 | error = 0; |
385 | break; | 369 | break; |
386 | } | 370 | } |
387 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 371 | if (!is_delete && error) { |
388 | entry->domainname = saved_domainname; | 372 | struct tomoyo_domain_keeper_entry *entry = |
389 | saved_domainname = NULL; | 373 | tomoyo_commit_ok(&e, sizeof(e)); |
390 | entry->program = saved_program; | 374 | if (entry) { |
391 | saved_program = NULL; | 375 | list_add_tail_rcu(&entry->list, |
392 | entry->is_not = is_not; | 376 | &tomoyo_domain_keeper_list); |
393 | entry->is_last_name = is_last_name; | 377 | error = 0; |
394 | list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); | 378 | } |
395 | entry = NULL; | ||
396 | error = 0; | ||
397 | } | 379 | } |
398 | mutex_unlock(&tomoyo_policy_lock); | 380 | mutex_unlock(&tomoyo_policy_lock); |
399 | out: | 381 | out: |
400 | tomoyo_put_name(saved_domainname); | 382 | tomoyo_put_name(e.domainname); |
401 | tomoyo_put_name(saved_program); | 383 | tomoyo_put_name(e.program); |
402 | kfree(entry); | ||
403 | return error; | 384 | return error; |
404 | } | 385 | } |
405 | 386 | ||
@@ -551,44 +532,38 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
551 | const char *aliased_name, | 532 | const char *aliased_name, |
552 | const bool is_delete) | 533 | const bool is_delete) |
553 | { | 534 | { |
554 | struct tomoyo_alias_entry *entry = NULL; | ||
555 | struct tomoyo_alias_entry *ptr; | 535 | struct tomoyo_alias_entry *ptr; |
556 | const struct tomoyo_path_info *saved_original_name; | 536 | struct tomoyo_alias_entry e = { }; |
557 | const struct tomoyo_path_info *saved_aliased_name; | ||
558 | int error = is_delete ? -ENOENT : -ENOMEM; | 537 | int error = is_delete ? -ENOENT : -ENOMEM; |
559 | 538 | ||
560 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || | 539 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || |
561 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) | 540 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) |
562 | return -EINVAL; /* No patterns allowed. */ | 541 | return -EINVAL; /* No patterns allowed. */ |
563 | saved_original_name = tomoyo_get_name(original_name); | 542 | e.original_name = tomoyo_get_name(original_name); |
564 | saved_aliased_name = tomoyo_get_name(aliased_name); | 543 | e.aliased_name = tomoyo_get_name(aliased_name); |
565 | if (!saved_original_name || !saved_aliased_name) | 544 | if (!e.original_name || !e.aliased_name) |
545 | goto out; | ||
546 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
566 | goto out; | 547 | goto out; |
567 | if (!is_delete) | ||
568 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
569 | mutex_lock(&tomoyo_policy_lock); | ||
570 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { | 548 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
571 | if (ptr->original_name != saved_original_name || | 549 | if (!tomoyo_is_same_alias_entry(ptr, &e)) |
572 | ptr->aliased_name != saved_aliased_name) | ||
573 | continue; | 550 | continue; |
574 | ptr->is_deleted = is_delete; | 551 | ptr->is_deleted = is_delete; |
575 | error = 0; | 552 | error = 0; |
576 | break; | 553 | break; |
577 | } | 554 | } |
578 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 555 | if (!is_delete && error) { |
579 | entry->original_name = saved_original_name; | 556 | struct tomoyo_alias_entry *entry = |
580 | saved_original_name = NULL; | 557 | tomoyo_commit_ok(&e, sizeof(e)); |
581 | entry->aliased_name = saved_aliased_name; | 558 | if (entry) { |
582 | saved_aliased_name = NULL; | 559 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); |
583 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); | 560 | error = 0; |
584 | entry = NULL; | 561 | } |
585 | error = 0; | ||
586 | } | 562 | } |
587 | mutex_unlock(&tomoyo_policy_lock); | 563 | mutex_unlock(&tomoyo_policy_lock); |
588 | out: | 564 | out: |
589 | tomoyo_put_name(saved_original_name); | 565 | tomoyo_put_name(e.original_name); |
590 | tomoyo_put_name(saved_aliased_name); | 566 | tomoyo_put_name(e.aliased_name); |
591 | kfree(entry); | ||
592 | return error; | 567 | return error; |
593 | } | 568 | } |
594 | 569 | ||
@@ -656,7 +631,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
656 | const u8 profile) | 631 | const u8 profile) |
657 | { | 632 | { |
658 | struct tomoyo_domain_info *entry; | 633 | struct tomoyo_domain_info *entry; |
659 | struct tomoyo_domain_info *domain; | 634 | struct tomoyo_domain_info *domain = NULL; |
660 | const struct tomoyo_path_info *saved_domainname; | 635 | const struct tomoyo_path_info *saved_domainname; |
661 | bool found = false; | 636 | bool found = false; |
662 | 637 | ||
@@ -665,8 +640,9 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
665 | saved_domainname = tomoyo_get_name(domainname); | 640 | saved_domainname = tomoyo_get_name(domainname); |
666 | if (!saved_domainname) | 641 | if (!saved_domainname) |
667 | return NULL; | 642 | return NULL; |
668 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 643 | entry = kzalloc(sizeof(*entry), GFP_NOFS); |
669 | mutex_lock(&tomoyo_policy_lock); | 644 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
645 | goto out; | ||
670 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 646 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
671 | if (domain->is_deleted || | 647 | if (domain->is_deleted || |
672 | tomoyo_pathcmp(saved_domainname, domain->domainname)) | 648 | tomoyo_pathcmp(saved_domainname, domain->domainname)) |
@@ -685,6 +661,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
685 | found = true; | 661 | found = true; |
686 | } | 662 | } |
687 | mutex_unlock(&tomoyo_policy_lock); | 663 | mutex_unlock(&tomoyo_policy_lock); |
664 | out: | ||
688 | tomoyo_put_name(saved_domainname); | 665 | tomoyo_put_name(saved_domainname); |
689 | kfree(entry); | 666 | kfree(entry); |
690 | return found ? domain : NULL; | 667 | return found ? domain : NULL; |
@@ -705,7 +682,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
705 | * This function assumes that the size of buffer returned by | 682 | * This function assumes that the size of buffer returned by |
706 | * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. | 683 | * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. |
707 | */ | 684 | */ |
708 | struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); | 685 | struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS); |
709 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); | 686 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); |
710 | struct tomoyo_domain_info *domain = NULL; | 687 | struct tomoyo_domain_info *domain = NULL; |
711 | const char *old_domain_name = old_domain->domainname->name; | 688 | const char *old_domain_name = old_domain->domainname->name; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 6f3fe76a1fde..1c6f8238ec47 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -45,6 +45,37 @@ static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { | |||
45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | 45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", |
46 | }; | 46 | }; |
47 | 47 | ||
48 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | ||
49 | { | ||
50 | if (!ptr) | ||
51 | return; | ||
52 | if (ptr->is_group) | ||
53 | tomoyo_put_path_group(ptr->group); | ||
54 | else | ||
55 | tomoyo_put_name(ptr->filename); | ||
56 | } | ||
57 | |||
58 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | ||
59 | const struct tomoyo_name_union *ptr) | ||
60 | { | ||
61 | if (ptr->is_group) | ||
62 | return tomoyo_path_matches_group(name, ptr->group, 1); | ||
63 | return tomoyo_path_matches_pattern(name, ptr->filename); | ||
64 | } | ||
65 | |||
66 | static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info | ||
67 | *name, | ||
68 | const struct tomoyo_name_union | ||
69 | *ptr, const bool may_use_pattern) | ||
70 | { | ||
71 | if (ptr->is_group) | ||
72 | return tomoyo_path_matches_group(name, ptr->group, | ||
73 | may_use_pattern); | ||
74 | if (may_use_pattern || !ptr->filename->is_patterned) | ||
75 | return tomoyo_path_matches_pattern(name, ptr->filename); | ||
76 | return false; | ||
77 | } | ||
78 | |||
48 | /** | 79 | /** |
49 | * tomoyo_path2keyword - Get the name of single path operation. | 80 | * tomoyo_path2keyword - Get the name of single path operation. |
50 | * | 81 | * |
@@ -100,7 +131,7 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | |||
100 | { | 131 | { |
101 | int error; | 132 | int error; |
102 | struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), | 133 | struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), |
103 | GFP_KERNEL); | 134 | GFP_NOFS); |
104 | 135 | ||
105 | if (!buf) | 136 | if (!buf) |
106 | return NULL; | 137 | return NULL; |
@@ -164,36 +195,36 @@ LIST_HEAD(tomoyo_globally_readable_list); | |||
164 | static int tomoyo_update_globally_readable_entry(const char *filename, | 195 | static int tomoyo_update_globally_readable_entry(const char *filename, |
165 | const bool is_delete) | 196 | const bool is_delete) |
166 | { | 197 | { |
167 | struct tomoyo_globally_readable_file_entry *entry = NULL; | ||
168 | struct tomoyo_globally_readable_file_entry *ptr; | 198 | struct tomoyo_globally_readable_file_entry *ptr; |
169 | const struct tomoyo_path_info *saved_filename; | 199 | struct tomoyo_globally_readable_file_entry e = { }; |
170 | int error = is_delete ? -ENOENT : -ENOMEM; | 200 | int error = is_delete ? -ENOENT : -ENOMEM; |
171 | 201 | ||
172 | if (!tomoyo_is_correct_path(filename, 1, 0, -1)) | 202 | if (!tomoyo_is_correct_path(filename, 1, 0, -1)) |
173 | return -EINVAL; | 203 | return -EINVAL; |
174 | saved_filename = tomoyo_get_name(filename); | 204 | e.filename = tomoyo_get_name(filename); |
175 | if (!saved_filename) | 205 | if (!e.filename) |
176 | return -ENOMEM; | 206 | return -ENOMEM; |
177 | if (!is_delete) | 207 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
178 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 208 | goto out; |
179 | mutex_lock(&tomoyo_policy_lock); | ||
180 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { | 209 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
181 | if (ptr->filename != saved_filename) | 210 | if (ptr->filename != e.filename) |
182 | continue; | 211 | continue; |
183 | ptr->is_deleted = is_delete; | 212 | ptr->is_deleted = is_delete; |
184 | error = 0; | 213 | error = 0; |
185 | break; | 214 | break; |
186 | } | 215 | } |
187 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 216 | if (!is_delete && error) { |
188 | entry->filename = saved_filename; | 217 | struct tomoyo_globally_readable_file_entry *entry = |
189 | saved_filename = NULL; | 218 | tomoyo_commit_ok(&e, sizeof(e)); |
190 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); | 219 | if (entry) { |
191 | entry = NULL; | 220 | list_add_tail_rcu(&entry->list, |
192 | error = 0; | 221 | &tomoyo_globally_readable_list); |
222 | error = 0; | ||
223 | } | ||
193 | } | 224 | } |
194 | mutex_unlock(&tomoyo_policy_lock); | 225 | mutex_unlock(&tomoyo_policy_lock); |
195 | tomoyo_put_name(saved_filename); | 226 | out: |
196 | kfree(entry); | 227 | tomoyo_put_name(e.filename); |
197 | return error; | 228 | return error; |
198 | } | 229 | } |
199 | 230 | ||
@@ -311,37 +342,34 @@ LIST_HEAD(tomoyo_pattern_list); | |||
311 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 342 | static int tomoyo_update_file_pattern_entry(const char *pattern, |
312 | const bool is_delete) | 343 | const bool is_delete) |
313 | { | 344 | { |
314 | struct tomoyo_pattern_entry *entry = NULL; | ||
315 | struct tomoyo_pattern_entry *ptr; | 345 | struct tomoyo_pattern_entry *ptr; |
316 | const struct tomoyo_path_info *saved_pattern; | 346 | struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) }; |
317 | int error = is_delete ? -ENOENT : -ENOMEM; | 347 | int error = is_delete ? -ENOENT : -ENOMEM; |
318 | 348 | ||
319 | saved_pattern = tomoyo_get_name(pattern); | 349 | if (!e.pattern) |
320 | if (!saved_pattern) | ||
321 | return error; | 350 | return error; |
322 | if (!saved_pattern->is_patterned) | 351 | if (!e.pattern->is_patterned) |
352 | goto out; | ||
353 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
323 | goto out; | 354 | goto out; |
324 | if (!is_delete) | ||
325 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
326 | mutex_lock(&tomoyo_policy_lock); | ||
327 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | 355 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
328 | if (saved_pattern != ptr->pattern) | 356 | if (e.pattern != ptr->pattern) |
329 | continue; | 357 | continue; |
330 | ptr->is_deleted = is_delete; | 358 | ptr->is_deleted = is_delete; |
331 | error = 0; | 359 | error = 0; |
332 | break; | 360 | break; |
333 | } | 361 | } |
334 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 362 | if (!is_delete && error) { |
335 | entry->pattern = saved_pattern; | 363 | struct tomoyo_pattern_entry *entry = |
336 | saved_pattern = NULL; | 364 | tomoyo_commit_ok(&e, sizeof(e)); |
337 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); | 365 | if (entry) { |
338 | entry = NULL; | 366 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); |
339 | error = 0; | 367 | error = 0; |
368 | } | ||
340 | } | 369 | } |
341 | mutex_unlock(&tomoyo_policy_lock); | 370 | mutex_unlock(&tomoyo_policy_lock); |
342 | out: | 371 | out: |
343 | kfree(entry); | 372 | tomoyo_put_name(e.pattern); |
344 | tomoyo_put_name(saved_pattern); | ||
345 | return error; | 373 | return error; |
346 | } | 374 | } |
347 | 375 | ||
@@ -464,36 +492,36 @@ LIST_HEAD(tomoyo_no_rewrite_list); | |||
464 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 492 | static int tomoyo_update_no_rewrite_entry(const char *pattern, |
465 | const bool is_delete) | 493 | const bool is_delete) |
466 | { | 494 | { |
467 | struct tomoyo_no_rewrite_entry *entry = NULL; | ||
468 | struct tomoyo_no_rewrite_entry *ptr; | 495 | struct tomoyo_no_rewrite_entry *ptr; |
469 | const struct tomoyo_path_info *saved_pattern; | 496 | struct tomoyo_no_rewrite_entry e = { }; |
470 | int error = is_delete ? -ENOENT : -ENOMEM; | 497 | int error = is_delete ? -ENOENT : -ENOMEM; |
471 | 498 | ||
472 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) | 499 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) |
473 | return -EINVAL; | 500 | return -EINVAL; |
474 | saved_pattern = tomoyo_get_name(pattern); | 501 | e.pattern = tomoyo_get_name(pattern); |
475 | if (!saved_pattern) | 502 | if (!e.pattern) |
476 | return error; | 503 | return error; |
477 | if (!is_delete) | 504 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
478 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 505 | goto out; |
479 | mutex_lock(&tomoyo_policy_lock); | ||
480 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | 506 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
481 | if (ptr->pattern != saved_pattern) | 507 | if (ptr->pattern != e.pattern) |
482 | continue; | 508 | continue; |
483 | ptr->is_deleted = is_delete; | 509 | ptr->is_deleted = is_delete; |
484 | error = 0; | 510 | error = 0; |
485 | break; | 511 | break; |
486 | } | 512 | } |
487 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 513 | if (!is_delete && error) { |
488 | entry->pattern = saved_pattern; | 514 | struct tomoyo_no_rewrite_entry *entry = |
489 | saved_pattern = NULL; | 515 | tomoyo_commit_ok(&e, sizeof(e)); |
490 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); | 516 | if (entry) { |
491 | entry = NULL; | 517 | list_add_tail_rcu(&entry->list, |
492 | error = 0; | 518 | &tomoyo_no_rewrite_list); |
519 | error = 0; | ||
520 | } | ||
493 | } | 521 | } |
494 | mutex_unlock(&tomoyo_policy_lock); | 522 | mutex_unlock(&tomoyo_policy_lock); |
495 | tomoyo_put_name(saved_pattern); | 523 | out: |
496 | kfree(entry); | 524 | tomoyo_put_name(e.pattern); |
497 | return error; | 525 | return error; |
498 | } | 526 | } |
499 | 527 | ||
@@ -640,13 +668,9 @@ static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, | |||
640 | if (!(acl->perm_high & (perm >> 16))) | 668 | if (!(acl->perm_high & (perm >> 16))) |
641 | continue; | 669 | continue; |
642 | } | 670 | } |
643 | if (may_use_pattern || !acl->filename->is_patterned) { | 671 | if (!tomoyo_compare_name_union_pattern(filename, &acl->name, |
644 | if (!tomoyo_path_matches_pattern(filename, | 672 | may_use_pattern)) |
645 | acl->filename)) | ||
646 | continue; | ||
647 | } else { | ||
648 | continue; | 673 | continue; |
649 | } | ||
650 | error = 0; | 674 | error = 0; |
651 | break; | 675 | break; |
652 | } | 676 | } |
@@ -805,70 +829,64 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
805 | struct tomoyo_domain_info *const domain, | 829 | struct tomoyo_domain_info *const domain, |
806 | const bool is_delete) | 830 | const bool is_delete) |
807 | { | 831 | { |
808 | static const u32 rw_mask = | 832 | static const u32 tomoyo_rw_mask = |
809 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); | 833 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); |
810 | const struct tomoyo_path_info *saved_filename; | 834 | const u32 perm = 1 << type; |
811 | struct tomoyo_acl_info *ptr; | 835 | struct tomoyo_acl_info *ptr; |
812 | struct tomoyo_path_acl *entry = NULL; | 836 | struct tomoyo_path_acl e = { |
837 | .head.type = TOMOYO_TYPE_PATH_ACL, | ||
838 | .perm_high = perm >> 16, | ||
839 | .perm = perm | ||
840 | }; | ||
813 | int error = is_delete ? -ENOENT : -ENOMEM; | 841 | int error = is_delete ? -ENOENT : -ENOMEM; |
814 | const u32 perm = 1 << type; | ||
815 | 842 | ||
843 | if (type == TOMOYO_TYPE_READ_WRITE) | ||
844 | e.perm |= tomoyo_rw_mask; | ||
816 | if (!domain) | 845 | if (!domain) |
817 | return -EINVAL; | 846 | return -EINVAL; |
818 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) | 847 | if (!tomoyo_parse_name_union(filename, &e.name)) |
819 | return -EINVAL; | 848 | return -EINVAL; |
820 | saved_filename = tomoyo_get_name(filename); | 849 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
821 | if (!saved_filename) | 850 | goto out; |
822 | return -ENOMEM; | ||
823 | if (!is_delete) | ||
824 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
825 | mutex_lock(&tomoyo_policy_lock); | ||
826 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 851 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
827 | struct tomoyo_path_acl *acl = | 852 | struct tomoyo_path_acl *acl = |
828 | container_of(ptr, struct tomoyo_path_acl, head); | 853 | container_of(ptr, struct tomoyo_path_acl, head); |
829 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) | 854 | if (!tomoyo_is_same_path_acl(acl, &e)) |
830 | continue; | ||
831 | if (acl->filename != saved_filename) | ||
832 | continue; | 855 | continue; |
833 | if (is_delete) { | 856 | if (is_delete) { |
834 | if (perm <= 0xFFFF) | 857 | if (perm <= 0xFFFF) |
835 | acl->perm &= ~perm; | 858 | acl->perm &= ~perm; |
836 | else | 859 | else |
837 | acl->perm_high &= ~(perm >> 16); | 860 | acl->perm_high &= ~(perm >> 16); |
838 | if ((acl->perm & rw_mask) != rw_mask) | 861 | if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) |
839 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); | 862 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); |
840 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) | 863 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
841 | acl->perm &= ~rw_mask; | 864 | acl->perm &= ~tomoyo_rw_mask; |
842 | } else { | 865 | } else { |
843 | if (perm <= 0xFFFF) | 866 | if (perm <= 0xFFFF) |
844 | acl->perm |= perm; | 867 | acl->perm |= perm; |
845 | else | 868 | else |
846 | acl->perm_high |= (perm >> 16); | 869 | acl->perm_high |= (perm >> 16); |
847 | if ((acl->perm & rw_mask) == rw_mask) | 870 | if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) |
848 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; | 871 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; |
849 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) | 872 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) |
850 | acl->perm |= rw_mask; | 873 | acl->perm |= tomoyo_rw_mask; |
851 | } | 874 | } |
852 | error = 0; | 875 | error = 0; |
853 | break; | 876 | break; |
854 | } | 877 | } |
855 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 878 | if (!is_delete && error) { |
856 | entry->head.type = TOMOYO_TYPE_PATH_ACL; | 879 | struct tomoyo_path_acl *entry = |
857 | if (perm <= 0xFFFF) | 880 | tomoyo_commit_ok(&e, sizeof(e)); |
858 | entry->perm = perm; | 881 | if (entry) { |
859 | else | 882 | list_add_tail_rcu(&entry->head.list, |
860 | entry->perm_high = (perm >> 16); | 883 | &domain->acl_info_list); |
861 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) | 884 | error = 0; |
862 | entry->perm |= rw_mask; | 885 | } |
863 | entry->filename = saved_filename; | ||
864 | saved_filename = NULL; | ||
865 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | ||
866 | entry = NULL; | ||
867 | error = 0; | ||
868 | } | 886 | } |
869 | mutex_unlock(&tomoyo_policy_lock); | 887 | mutex_unlock(&tomoyo_policy_lock); |
870 | kfree(entry); | 888 | out: |
871 | tomoyo_put_name(saved_filename); | 889 | tomoyo_put_name_union(&e.name); |
872 | return error; | 890 | return error; |
873 | } | 891 | } |
874 | 892 | ||
@@ -890,32 +908,25 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
890 | struct tomoyo_domain_info *const domain, | 908 | struct tomoyo_domain_info *const domain, |
891 | const bool is_delete) | 909 | const bool is_delete) |
892 | { | 910 | { |
893 | const struct tomoyo_path_info *saved_filename1; | 911 | const u8 perm = 1 << type; |
894 | const struct tomoyo_path_info *saved_filename2; | 912 | struct tomoyo_path2_acl e = { |
913 | .head.type = TOMOYO_TYPE_PATH2_ACL, | ||
914 | .perm = perm | ||
915 | }; | ||
895 | struct tomoyo_acl_info *ptr; | 916 | struct tomoyo_acl_info *ptr; |
896 | struct tomoyo_path2_acl *entry = NULL; | ||
897 | int error = is_delete ? -ENOENT : -ENOMEM; | 917 | int error = is_delete ? -ENOENT : -ENOMEM; |
898 | const u8 perm = 1 << type; | ||
899 | 918 | ||
900 | if (!domain) | 919 | if (!domain) |
901 | return -EINVAL; | 920 | return -EINVAL; |
902 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || | 921 | if (!tomoyo_parse_name_union(filename1, &e.name1) || |
903 | !tomoyo_is_correct_path(filename2, 0, 0, 0)) | 922 | !tomoyo_parse_name_union(filename2, &e.name2)) |
904 | return -EINVAL; | 923 | goto out; |
905 | saved_filename1 = tomoyo_get_name(filename1); | 924 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
906 | saved_filename2 = tomoyo_get_name(filename2); | ||
907 | if (!saved_filename1 || !saved_filename2) | ||
908 | goto out; | 925 | goto out; |
909 | if (!is_delete) | ||
910 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
911 | mutex_lock(&tomoyo_policy_lock); | ||
912 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 926 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
913 | struct tomoyo_path2_acl *acl = | 927 | struct tomoyo_path2_acl *acl = |
914 | container_of(ptr, struct tomoyo_path2_acl, head); | 928 | container_of(ptr, struct tomoyo_path2_acl, head); |
915 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) | 929 | if (!tomoyo_is_same_path2_acl(acl, &e)) |
916 | continue; | ||
917 | if (acl->filename1 != saved_filename1 || | ||
918 | acl->filename2 != saved_filename2) | ||
919 | continue; | 930 | continue; |
920 | if (is_delete) | 931 | if (is_delete) |
921 | acl->perm &= ~perm; | 932 | acl->perm &= ~perm; |
@@ -924,22 +935,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
924 | error = 0; | 935 | error = 0; |
925 | break; | 936 | break; |
926 | } | 937 | } |
927 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 938 | if (!is_delete && error) { |
928 | entry->head.type = TOMOYO_TYPE_PATH2_ACL; | 939 | struct tomoyo_path2_acl *entry = |
929 | entry->perm = perm; | 940 | tomoyo_commit_ok(&e, sizeof(e)); |
930 | entry->filename1 = saved_filename1; | 941 | if (entry) { |
931 | saved_filename1 = NULL; | 942 | list_add_tail_rcu(&entry->head.list, |
932 | entry->filename2 = saved_filename2; | 943 | &domain->acl_info_list); |
933 | saved_filename2 = NULL; | 944 | error = 0; |
934 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | 945 | } |
935 | entry = NULL; | ||
936 | error = 0; | ||
937 | } | 946 | } |
938 | mutex_unlock(&tomoyo_policy_lock); | 947 | mutex_unlock(&tomoyo_policy_lock); |
939 | out: | 948 | out: |
940 | tomoyo_put_name(saved_filename1); | 949 | tomoyo_put_name_union(&e.name1); |
941 | tomoyo_put_name(saved_filename2); | 950 | tomoyo_put_name_union(&e.name2); |
942 | kfree(entry); | ||
943 | return error; | 951 | return error; |
944 | } | 952 | } |
945 | 953 | ||
@@ -992,9 +1000,9 @@ static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, | |||
992 | acl = container_of(ptr, struct tomoyo_path2_acl, head); | 1000 | acl = container_of(ptr, struct tomoyo_path2_acl, head); |
993 | if (!(acl->perm & perm)) | 1001 | if (!(acl->perm & perm)) |
994 | continue; | 1002 | continue; |
995 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) | 1003 | if (!tomoyo_compare_name_union(filename1, &acl->name1)) |
996 | continue; | 1004 | continue; |
997 | if (!tomoyo_path_matches_pattern(filename2, acl->filename2)) | 1005 | if (!tomoyo_compare_name_union(filename2, &acl->name2)) |
998 | continue; | 1006 | continue; |
999 | error = 0; | 1007 | error = 0; |
1000 | break; | 1008 | break; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index d9ad35bc7fa8..b9cc71b04314 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | 13 | ||
14 | enum tomoyo_gc_id { | 14 | enum tomoyo_gc_id { |
15 | TOMOYO_ID_PATH_GROUP, | ||
16 | TOMOYO_ID_PATH_GROUP_MEMBER, | ||
15 | TOMOYO_ID_DOMAIN_INITIALIZER, | 17 | TOMOYO_ID_DOMAIN_INITIALIZER, |
16 | TOMOYO_ID_DOMAIN_KEEPER, | 18 | TOMOYO_ID_DOMAIN_KEEPER, |
17 | TOMOYO_ID_ALIAS, | 19 | TOMOYO_ID_ALIAS, |
@@ -91,15 +93,15 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) | |||
91 | { | 93 | { |
92 | struct tomoyo_path_acl *entry | 94 | struct tomoyo_path_acl *entry |
93 | = container_of(acl, typeof(*entry), head); | 95 | = container_of(acl, typeof(*entry), head); |
94 | tomoyo_put_name(entry->filename); | 96 | tomoyo_put_name_union(&entry->name); |
95 | } | 97 | } |
96 | break; | 98 | break; |
97 | case TOMOYO_TYPE_PATH2_ACL: | 99 | case TOMOYO_TYPE_PATH2_ACL: |
98 | { | 100 | { |
99 | struct tomoyo_path2_acl *entry | 101 | struct tomoyo_path2_acl *entry |
100 | = container_of(acl, typeof(*entry), head); | 102 | = container_of(acl, typeof(*entry), head); |
101 | tomoyo_put_name(entry->filename1); | 103 | tomoyo_put_name_union(&entry->name1); |
102 | tomoyo_put_name(entry->filename2); | 104 | tomoyo_put_name_union(&entry->name2); |
103 | } | 105 | } |
104 | break; | 106 | break; |
105 | default: | 107 | default: |
@@ -149,9 +151,21 @@ static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) | |||
149 | { | 151 | { |
150 | } | 152 | } |
151 | 153 | ||
154 | static void tomoyo_del_path_group_member(struct tomoyo_path_group_member | ||
155 | *member) | ||
156 | { | ||
157 | tomoyo_put_name(member->member_name); | ||
158 | } | ||
159 | |||
160 | static void tomoyo_del_path_group(struct tomoyo_path_group *group) | ||
161 | { | ||
162 | tomoyo_put_name(group->group_name); | ||
163 | } | ||
164 | |||
152 | static void tomoyo_collect_entry(void) | 165 | static void tomoyo_collect_entry(void) |
153 | { | 166 | { |
154 | mutex_lock(&tomoyo_policy_lock); | 167 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
168 | return; | ||
155 | { | 169 | { |
156 | struct tomoyo_globally_readable_file_entry *ptr; | 170 | struct tomoyo_globally_readable_file_entry *ptr; |
157 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, | 171 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, |
@@ -275,8 +289,6 @@ static void tomoyo_collect_entry(void) | |||
275 | break; | 289 | break; |
276 | } | 290 | } |
277 | } | 291 | } |
278 | mutex_unlock(&tomoyo_policy_lock); | ||
279 | mutex_lock(&tomoyo_name_list_lock); | ||
280 | { | 292 | { |
281 | int i; | 293 | int i; |
282 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { | 294 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { |
@@ -294,7 +306,30 @@ static void tomoyo_collect_entry(void) | |||
294 | } | 306 | } |
295 | } | 307 | } |
296 | } | 308 | } |
297 | mutex_unlock(&tomoyo_name_list_lock); | 309 | { |
310 | struct tomoyo_path_group *group; | ||
311 | list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { | ||
312 | struct tomoyo_path_group_member *member; | ||
313 | list_for_each_entry_rcu(member, &group->member_list, | ||
314 | list) { | ||
315 | if (!member->is_deleted) | ||
316 | continue; | ||
317 | if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, | ||
318 | member)) | ||
319 | list_del_rcu(&member->list); | ||
320 | else | ||
321 | break; | ||
322 | } | ||
323 | if (!list_empty(&group->member_list) || | ||
324 | atomic_read(&group->users)) | ||
325 | continue; | ||
326 | if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) | ||
327 | list_del_rcu(&group->list); | ||
328 | else | ||
329 | break; | ||
330 | } | ||
331 | } | ||
332 | mutex_unlock(&tomoyo_policy_lock); | ||
298 | } | 333 | } |
299 | 334 | ||
300 | static void tomoyo_kfree_entry(void) | 335 | static void tomoyo_kfree_entry(void) |
@@ -335,6 +370,12 @@ static void tomoyo_kfree_entry(void) | |||
335 | if (!tomoyo_del_domain(p->element)) | 370 | if (!tomoyo_del_domain(p->element)) |
336 | continue; | 371 | continue; |
337 | break; | 372 | break; |
373 | case TOMOYO_ID_PATH_GROUP_MEMBER: | ||
374 | tomoyo_del_path_group_member(p->element); | ||
375 | break; | ||
376 | case TOMOYO_ID_PATH_GROUP: | ||
377 | tomoyo_del_path_group(p->element); | ||
378 | break; | ||
338 | default: | 379 | default: |
339 | printk(KERN_WARNING "Unknown type\n"); | 380 | printk(KERN_WARNING "Unknown type\n"); |
340 | break; | 381 | break; |
diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c new file mode 100644 index 000000000000..c988041c8e1c --- /dev/null +++ b/security/tomoyo/path_group.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * security/tomoyo/path_group.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
5 | */ | ||
6 | |||
7 | #include <linux/slab.h> | ||
8 | #include "common.h" | ||
9 | /* The list for "struct ccs_path_group". */ | ||
10 | LIST_HEAD(tomoyo_path_group_list); | ||
11 | |||
12 | /** | ||
13 | * tomoyo_get_path_group - Allocate memory for "struct tomoyo_path_group". | ||
14 | * | ||
15 | * @group_name: The name of pathname group. | ||
16 | * | ||
17 | * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise. | ||
18 | */ | ||
19 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name) | ||
20 | { | ||
21 | struct tomoyo_path_group *entry = NULL; | ||
22 | struct tomoyo_path_group *group = NULL; | ||
23 | const struct tomoyo_path_info *saved_group_name; | ||
24 | int error = -ENOMEM; | ||
25 | if (!tomoyo_is_correct_path(group_name, 0, 0, 0) || | ||
26 | !group_name[0]) | ||
27 | return NULL; | ||
28 | saved_group_name = tomoyo_get_name(group_name); | ||
29 | if (!saved_group_name) | ||
30 | return NULL; | ||
31 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
32 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
33 | goto out; | ||
34 | list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { | ||
35 | if (saved_group_name != group->group_name) | ||
36 | continue; | ||
37 | atomic_inc(&group->users); | ||
38 | error = 0; | ||
39 | break; | ||
40 | } | ||
41 | if (error && tomoyo_memory_ok(entry)) { | ||
42 | INIT_LIST_HEAD(&entry->member_list); | ||
43 | entry->group_name = saved_group_name; | ||
44 | saved_group_name = NULL; | ||
45 | atomic_set(&entry->users, 1); | ||
46 | list_add_tail_rcu(&entry->list, &tomoyo_path_group_list); | ||
47 | group = entry; | ||
48 | entry = NULL; | ||
49 | error = 0; | ||
50 | } | ||
51 | mutex_unlock(&tomoyo_policy_lock); | ||
52 | out: | ||
53 | tomoyo_put_name(saved_group_name); | ||
54 | kfree(entry); | ||
55 | return !error ? group : NULL; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list. | ||
60 | * | ||
61 | * @data: String to parse. | ||
62 | * @is_delete: True if it is a delete request. | ||
63 | * | ||
64 | * Returns 0 on success, nagative value otherwise. | ||
65 | */ | ||
66 | int tomoyo_write_path_group_policy(char *data, const bool is_delete) | ||
67 | { | ||
68 | struct tomoyo_path_group *group; | ||
69 | struct tomoyo_path_group_member *member; | ||
70 | struct tomoyo_path_group_member e = { }; | ||
71 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
72 | char *w[2]; | ||
73 | if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) | ||
74 | return -EINVAL; | ||
75 | group = tomoyo_get_path_group(w[0]); | ||
76 | if (!group) | ||
77 | return -ENOMEM; | ||
78 | e.member_name = tomoyo_get_name(w[1]); | ||
79 | if (!e.member_name) | ||
80 | goto out; | ||
81 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
82 | goto out; | ||
83 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
84 | if (member->member_name != e.member_name) | ||
85 | continue; | ||
86 | member->is_deleted = is_delete; | ||
87 | error = 0; | ||
88 | break; | ||
89 | } | ||
90 | if (!is_delete && error) { | ||
91 | struct tomoyo_path_group_member *entry = | ||
92 | tomoyo_commit_ok(&e, sizeof(e)); | ||
93 | if (entry) { | ||
94 | list_add_tail_rcu(&entry->list, &group->member_list); | ||
95 | error = 0; | ||
96 | } | ||
97 | } | ||
98 | mutex_unlock(&tomoyo_policy_lock); | ||
99 | out: | ||
100 | tomoyo_put_name(e.member_name); | ||
101 | tomoyo_put_path_group(group); | ||
102 | return error; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * tomoyo_read_path_group_policy - Read "struct tomoyo_path_group" list. | ||
107 | * | ||
108 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
109 | * | ||
110 | * Returns true on success, false otherwise. | ||
111 | * | ||
112 | * Caller holds tomoyo_read_lock(). | ||
113 | */ | ||
114 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head) | ||
115 | { | ||
116 | struct list_head *gpos; | ||
117 | struct list_head *mpos; | ||
118 | list_for_each_cookie(gpos, head->read_var1, &tomoyo_path_group_list) { | ||
119 | struct tomoyo_path_group *group; | ||
120 | group = list_entry(gpos, struct tomoyo_path_group, list); | ||
121 | list_for_each_cookie(mpos, head->read_var2, | ||
122 | &group->member_list) { | ||
123 | struct tomoyo_path_group_member *member; | ||
124 | member = list_entry(mpos, | ||
125 | struct tomoyo_path_group_member, | ||
126 | list); | ||
127 | if (member->is_deleted) | ||
128 | continue; | ||
129 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_PATH_GROUP | ||
130 | "%s %s\n", | ||
131 | group->group_name->name, | ||
132 | member->member_name->name)) | ||
133 | return false; | ||
134 | } | ||
135 | } | ||
136 | return true; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. | ||
141 | * | ||
142 | * @pathname: The name of pathname. | ||
143 | * @group: Pointer to "struct tomoyo_path_group". | ||
144 | * @may_use_pattern: True if wild card is permitted. | ||
145 | * | ||
146 | * Returns true if @pathname matches pathnames in @group, false otherwise. | ||
147 | * | ||
148 | * Caller holds tomoyo_read_lock(). | ||
149 | */ | ||
150 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | ||
151 | const struct tomoyo_path_group *group, | ||
152 | const bool may_use_pattern) | ||
153 | { | ||
154 | struct tomoyo_path_group_member *member; | ||
155 | bool matched = false; | ||
156 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
157 | if (member->is_deleted) | ||
158 | continue; | ||
159 | if (!member->member_name->is_patterned) { | ||
160 | if (tomoyo_pathcmp(pathname, member->member_name)) | ||
161 | continue; | ||
162 | } else if (may_use_pattern) { | ||
163 | if (!tomoyo_path_matches_pattern(pathname, | ||
164 | member->member_name)) | ||
165 | continue; | ||
166 | } else | ||
167 | continue; | ||
168 | matched = true; | ||
169 | break; | ||
170 | } | ||
171 | return matched; | ||
172 | } | ||
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index c225c65ce426..d1b96f019621 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
@@ -139,7 +139,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, | |||
139 | */ | 139 | */ |
140 | char *tomoyo_realpath_from_path(struct path *path) | 140 | char *tomoyo_realpath_from_path(struct path *path) |
141 | { | 141 | { |
142 | char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL); | 142 | char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS); |
143 | 143 | ||
144 | BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) | 144 | BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) |
145 | <= TOMOYO_MAX_PATHNAME_LEN - 1); | 145 | <= TOMOYO_MAX_PATHNAME_LEN - 1); |
@@ -223,6 +223,25 @@ bool tomoyo_memory_ok(void *ptr) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * tomoyo_commit_ok - Check memory quota. | ||
227 | * | ||
228 | * @data: Data to copy from. | ||
229 | * @size: Size in byte. | ||
230 | * | ||
231 | * Returns pointer to allocated memory on success, NULL otherwise. | ||
232 | */ | ||
233 | void *tomoyo_commit_ok(void *data, const unsigned int size) | ||
234 | { | ||
235 | void *ptr = kzalloc(size, GFP_NOFS); | ||
236 | if (tomoyo_memory_ok(ptr)) { | ||
237 | memmove(ptr, data, size); | ||
238 | memset(data, 0, size); | ||
239 | return ptr; | ||
240 | } | ||
241 | return NULL; | ||
242 | } | ||
243 | |||
244 | /** | ||
226 | * tomoyo_memory_free - Free memory for elements. | 245 | * tomoyo_memory_free - Free memory for elements. |
227 | * | 246 | * |
228 | * @ptr: Pointer to allocated memory. | 247 | * @ptr: Pointer to allocated memory. |
@@ -240,8 +259,6 @@ void tomoyo_memory_free(void *ptr) | |||
240 | * "const struct tomoyo_path_info *". | 259 | * "const struct tomoyo_path_info *". |
241 | */ | 260 | */ |
242 | struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 261 | struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
243 | /* Lock for protecting tomoyo_name_list . */ | ||
244 | DEFINE_MUTEX(tomoyo_name_list_lock); | ||
245 | 262 | ||
246 | /** | 263 | /** |
247 | * tomoyo_get_name - Allocate permanent memory for string data. | 264 | * tomoyo_get_name - Allocate permanent memory for string data. |
@@ -263,14 +280,15 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) | |||
263 | len = strlen(name) + 1; | 280 | len = strlen(name) + 1; |
264 | hash = full_name_hash((const unsigned char *) name, len - 1); | 281 | hash = full_name_hash((const unsigned char *) name, len - 1); |
265 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; | 282 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; |
266 | mutex_lock(&tomoyo_name_list_lock); | 283 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
284 | return NULL; | ||
267 | list_for_each_entry(ptr, head, list) { | 285 | list_for_each_entry(ptr, head, list) { |
268 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) | 286 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) |
269 | continue; | 287 | continue; |
270 | atomic_inc(&ptr->users); | 288 | atomic_inc(&ptr->users); |
271 | goto out; | 289 | goto out; |
272 | } | 290 | } |
273 | ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); | 291 | ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); |
274 | allocated_len = ptr ? ksize(ptr) : 0; | 292 | allocated_len = ptr ? ksize(ptr) : 0; |
275 | if (!ptr || (tomoyo_quota_for_policy && | 293 | if (!ptr || (tomoyo_quota_for_policy && |
276 | atomic_read(&tomoyo_policy_memory_size) + allocated_len | 294 | atomic_read(&tomoyo_policy_memory_size) + allocated_len |
@@ -290,7 +308,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) | |||
290 | tomoyo_fill_path_info(&ptr->entry); | 308 | tomoyo_fill_path_info(&ptr->entry); |
291 | list_add_tail(&ptr->list, head); | 309 | list_add_tail(&ptr->list, head); |
292 | out: | 310 | out: |
293 | mutex_unlock(&tomoyo_name_list_lock); | 311 | mutex_unlock(&tomoyo_policy_lock); |
294 | return ptr ? &ptr->entry : NULL; | 312 | return ptr ? &ptr->entry : NULL; |
295 | } | 313 | } |
296 | 314 | ||