Commit 2e1deaad1e48453cea782854ab87df3f78c121c2
Exists in
master
and in
20 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem update from James Morris: "Just some minor updates across the subsystem" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: ima: eliminate passing d_name.name to process_measurement() TPM: Retry SaveState command in suspend path tpm/tpm_i2c_infineon: Add small comment about return value of __i2c_transfer tpm/tpm_i2c_infineon.c: Add OF attributes type and name to the of_device_id table entries tpm_i2c_stm_st33: Remove duplicate inclusion of header files tpm: Add support for new Infineon I2C TPM (SLB 9645 TT 1.2 I2C) char/tpm: Convert struct i2c_msg initialization to C99 format drivers/char/tpm/tpm_ppi: use strlcpy instead of strncpy tpm/tpm_i2c_stm_st33: formatting and white space changes Smack: include magic.h in smackfs.c selinux: make security_sb_clone_mnt_opts return an error on context mismatch seccomp: allow BPF_XOR based ALU instructions. Fix NULL pointer dereference in smack_inode_unlink() and smack_inode_rmdir() Smack: add support for modification of existing rules smack: SMACK_MAGIC to include/uapi/linux/magic.h Smack: add missing support for transmute bit in smack_str_from_perm() Smack: prevent revoke-subject from failing when unseen label is written to it tomoyo: use DEFINE_SRCU() to define tomoyo_ss tomoyo: use DEFINE_SRCU() to define tomoyo_ss
Showing 20 changed files Side-by-side Diff
- Documentation/devicetree/bindings/i2c/trivial-devices.txt
- Documentation/security/Smack.txt
- drivers/char/tpm/tpm.c
- drivers/char/tpm/tpm.h
- drivers/char/tpm/tpm_i2c_infineon.c
- drivers/char/tpm/tpm_i2c_stm_st33.c
- drivers/char/tpm/tpm_ppi.c
- fs/nfs/super.c
- include/linux/security.h
- include/uapi/linux/magic.h
- kernel/seccomp.c
- security/capability.c
- security/integrity/ima/ima_main.c
- security/security.c
- security/selinux/hooks.c
- security/smack/smack.h
- security/smack/smack_access.c
- security/smack/smack_lsm.c
- security/smack/smackfs.c
- security/tomoyo/tomoyo.c
Documentation/devicetree/bindings/i2c/trivial-devices.txt
... | ... | @@ -35,6 +35,8 @@ |
35 | 35 | fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer |
36 | 36 | fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller |
37 | 37 | fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec |
38 | +infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz) | |
39 | +infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz) | |
38 | 40 | maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator |
39 | 41 | maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs |
40 | 42 | maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface |
Documentation/security/Smack.txt
... | ... | @@ -117,6 +117,17 @@ |
117 | 117 | ambient |
118 | 118 | This contains the Smack label applied to unlabeled network |
119 | 119 | packets. |
120 | +change-rule | |
121 | + This interface allows modification of existing access control rules. | |
122 | + The format accepted on write is: | |
123 | + "%s %s %s %s" | |
124 | + where the first string is the subject label, the second the | |
125 | + object label, the third the access to allow and the fourth the | |
126 | + access to deny. The access strings may contain only the characters | |
127 | + "rwxat-". If a rule for a given subject and object exists it will be | |
128 | + modified by enabling the permissions in the third string and disabling | |
129 | + those in the fourth string. If there is no such rule it will be | |
130 | + created using the access specified in the third and the fourth strings. | |
120 | 131 | cipso |
121 | 132 | This interface allows a specific CIPSO header to be assigned |
122 | 133 | to a Smack label. The format accepted on write is: |
drivers/char/tpm/tpm.c
... | ... | @@ -1337,7 +1337,7 @@ |
1337 | 1337 | { |
1338 | 1338 | struct tpm_chip *chip = dev_get_drvdata(dev); |
1339 | 1339 | struct tpm_cmd_t cmd; |
1340 | - int rc; | |
1340 | + int rc, try; | |
1341 | 1341 | |
1342 | 1342 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; |
1343 | 1343 | |
... | ... | @@ -1355,9 +1355,32 @@ |
1355 | 1355 | } |
1356 | 1356 | |
1357 | 1357 | /* now do the actual savestate */ |
1358 | - cmd.header.in = savestate_header; | |
1359 | - rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, | |
1360 | - "sending savestate before suspend"); | |
1358 | + for (try = 0; try < TPM_RETRY; try++) { | |
1359 | + cmd.header.in = savestate_header; | |
1360 | + rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); | |
1361 | + | |
1362 | + /* | |
1363 | + * If the TPM indicates that it is too busy to respond to | |
1364 | + * this command then retry before giving up. It can take | |
1365 | + * several seconds for this TPM to be ready. | |
1366 | + * | |
1367 | + * This can happen if the TPM has already been sent the | |
1368 | + * SaveState command before the driver has loaded. TCG 1.2 | |
1369 | + * specification states that any communication after SaveState | |
1370 | + * may cause the TPM to invalidate previously saved state. | |
1371 | + */ | |
1372 | + if (rc != TPM_WARN_RETRY) | |
1373 | + break; | |
1374 | + msleep(TPM_TIMEOUT_RETRY); | |
1375 | + } | |
1376 | + | |
1377 | + if (rc) | |
1378 | + dev_err(chip->dev, | |
1379 | + "Error (%d) sending savestate before suspend\n", rc); | |
1380 | + else if (try > 0) | |
1381 | + dev_warn(chip->dev, "TPM savestate took %dms\n", | |
1382 | + try * TPM_TIMEOUT_RETRY); | |
1383 | + | |
1361 | 1384 | return rc; |
1362 | 1385 | } |
1363 | 1386 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); |
drivers/char/tpm/tpm.h
... | ... | @@ -32,10 +32,12 @@ |
32 | 32 | TPM_MINOR = 224, /* officially assigned */ |
33 | 33 | TPM_BUFSIZE = 4096, |
34 | 34 | TPM_NUM_DEVICES = 256, |
35 | + TPM_RETRY = 50, /* 5 seconds */ | |
35 | 36 | }; |
36 | 37 | |
37 | 38 | enum tpm_timeout { |
38 | 39 | TPM_TIMEOUT = 5, /* msecs */ |
40 | + TPM_TIMEOUT_RETRY = 100 /* msecs */ | |
39 | 41 | }; |
40 | 42 | |
41 | 43 | /* TPM addresses */ |
... | ... | @@ -44,6 +46,7 @@ |
44 | 46 | TPM_ADDR = 0x4E, |
45 | 47 | }; |
46 | 48 | |
49 | +#define TPM_WARN_RETRY 0x800 | |
47 | 50 | #define TPM_WARN_DOING_SELFTEST 0x802 |
48 | 51 | #define TPM_ERR_DEACTIVATED 0x6 |
49 | 52 | #define TPM_ERR_DISABLED 0x7 |
drivers/char/tpm/tpm_i2c_infineon.c
1 | 1 | /* |
2 | - * Copyright (C) 2012 Infineon Technologies | |
2 | + * Copyright (C) 2012,2013 Infineon Technologies | |
3 | 3 | * |
4 | 4 | * Authors: |
5 | 5 | * Peter Huewe <peter.huewe@infineon.com> |
6 | 6 | |
7 | 7 | |
... | ... | @@ -56,13 +56,21 @@ |
56 | 56 | #define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) |
57 | 57 | |
58 | 58 | /* expected value for DIDVID register */ |
59 | -#define TPM_TIS_I2C_DID_VID 0x000b15d1L | |
59 | +#define TPM_TIS_I2C_DID_VID_9635 0xd1150b00L | |
60 | +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L | |
60 | 61 | |
62 | +enum i2c_chip_type { | |
63 | + SLB9635, | |
64 | + SLB9645, | |
65 | + UNKNOWN, | |
66 | +}; | |
67 | + | |
61 | 68 | /* Structure to store I2C TPM specific stuff */ |
62 | 69 | struct tpm_inf_dev { |
63 | 70 | struct i2c_client *client; |
64 | 71 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ |
65 | 72 | struct tpm_chip *chip; |
73 | + enum i2c_chip_type chip_type; | |
66 | 74 | }; |
67 | 75 | |
68 | 76 | static struct tpm_inf_dev tpm_dev; |
69 | 77 | |
... | ... | @@ -90,10 +98,20 @@ |
90 | 98 | static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) |
91 | 99 | { |
92 | 100 | |
93 | - struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr }; | |
94 | - struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer }; | |
101 | + struct i2c_msg msg1 = { | |
102 | + .addr = tpm_dev.client->addr, | |
103 | + .len = 1, | |
104 | + .buf = &addr | |
105 | + }; | |
106 | + struct i2c_msg msg2 = { | |
107 | + .addr = tpm_dev.client->addr, | |
108 | + .flags = I2C_M_RD, | |
109 | + .len = len, | |
110 | + .buf = buffer | |
111 | + }; | |
112 | + struct i2c_msg msgs[] = {msg1, msg2}; | |
95 | 113 | |
96 | - int rc; | |
114 | + int rc = 0; | |
97 | 115 | int count; |
98 | 116 | |
99 | 117 | /* Lock the adapter for the duration of the whole sequence. */ |
100 | 118 | |
101 | 119 | |
102 | 120 | |
103 | 121 | |
... | ... | @@ -101,30 +119,53 @@ |
101 | 119 | return -EOPNOTSUPP; |
102 | 120 | i2c_lock_adapter(tpm_dev.client->adapter); |
103 | 121 | |
104 | - for (count = 0; count < MAX_COUNT; count++) { | |
105 | - rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | |
106 | - if (rc > 0) | |
107 | - break; /* break here to skip sleep */ | |
122 | + if (tpm_dev.chip_type == SLB9645) { | |
123 | + /* use a combined read for newer chips | |
124 | + * unfortunately the smbus functions are not suitable due to | |
125 | + * the 32 byte limit of the smbus. | |
126 | + * retries should usually not be needed, but are kept just to | |
127 | + * be on the safe side. | |
128 | + */ | |
129 | + for (count = 0; count < MAX_COUNT; count++) { | |
130 | + rc = __i2c_transfer(tpm_dev.client->adapter, msgs, 2); | |
131 | + if (rc > 0) | |
132 | + break; /* break here to skip sleep */ | |
133 | + usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
134 | + } | |
135 | + } else { | |
136 | + /* slb9635 protocol should work in all cases */ | |
137 | + for (count = 0; count < MAX_COUNT; count++) { | |
138 | + rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | |
139 | + if (rc > 0) | |
140 | + break; /* break here to skip sleep */ | |
108 | 141 | |
109 | - usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
110 | - } | |
142 | + usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
143 | + } | |
111 | 144 | |
112 | - if (rc <= 0) | |
113 | - goto out; | |
145 | + if (rc <= 0) | |
146 | + goto out; | |
114 | 147 | |
115 | - /* After the TPM has successfully received the register address it needs | |
116 | - * some time, thus we're sleeping here again, before retrieving the data | |
117 | - */ | |
118 | - for (count = 0; count < MAX_COUNT; count++) { | |
119 | - usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
120 | - rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); | |
121 | - if (rc > 0) | |
122 | - break; | |
123 | - | |
148 | + /* After the TPM has successfully received the register address | |
149 | + * it needs some time, thus we're sleeping here again, before | |
150 | + * retrieving the data | |
151 | + */ | |
152 | + for (count = 0; count < MAX_COUNT; count++) { | |
153 | + usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
154 | + rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); | |
155 | + if (rc > 0) | |
156 | + break; | |
157 | + } | |
124 | 158 | } |
125 | 159 | |
126 | 160 | out: |
127 | 161 | i2c_unlock_adapter(tpm_dev.client->adapter); |
162 | + /* take care of 'guard time' */ | |
163 | + usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
164 | + | |
165 | + /* __i2c_transfer returns the number of successfully transferred | |
166 | + * messages. | |
167 | + * So rc should be greater than 0 here otherwise we have an error. | |
168 | + */ | |
128 | 169 | if (rc <= 0) |
129 | 170 | return -EIO; |
130 | 171 | |
... | ... | @@ -138,7 +179,11 @@ |
138 | 179 | int rc = -EIO; |
139 | 180 | int count; |
140 | 181 | |
141 | - struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf }; | |
182 | + struct i2c_msg msg1 = { | |
183 | + .addr = tpm_dev.client->addr, | |
184 | + .len = len + 1, | |
185 | + .buf = tpm_dev.buf | |
186 | + }; | |
142 | 187 | |
143 | 188 | if (len > TPM_BUFSIZE) |
144 | 189 | return -EINVAL; |
145 | 190 | |
146 | 191 | |
... | ... | @@ -154,16 +199,24 @@ |
154 | 199 | /* |
155 | 200 | * NOTE: We have to use these special mechanisms here and unfortunately |
156 | 201 | * cannot rely on the standard behavior of i2c_transfer. |
202 | + * Even for newer chips the smbus functions are not | |
203 | + * suitable due to the 32 byte limit of the smbus. | |
157 | 204 | */ |
158 | 205 | for (count = 0; count < max_count; count++) { |
159 | 206 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); |
160 | 207 | if (rc > 0) |
161 | 208 | break; |
162 | - | |
163 | 209 | usleep_range(sleep_low, sleep_hi); |
164 | 210 | } |
165 | 211 | |
166 | 212 | i2c_unlock_adapter(tpm_dev.client->adapter); |
213 | + /* take care of 'guard time' */ | |
214 | + usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | |
215 | + | |
216 | + /* __i2c_transfer returns the number of successfully transferred | |
217 | + * messages. | |
218 | + * So rc should be greater than 0 here otherwise we have an error. | |
219 | + */ | |
167 | 220 | if (rc <= 0) |
168 | 221 | return -EIO; |
169 | 222 | |
... | ... | @@ -283,11 +336,18 @@ |
283 | 336 | static u8 tpm_tis_i2c_status(struct tpm_chip *chip) |
284 | 337 | { |
285 | 338 | /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ |
286 | - u8 buf; | |
287 | - if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) | |
288 | - return 0; | |
289 | - else | |
290 | - return buf; | |
339 | + u8 buf = 0xFF; | |
340 | + u8 i = 0; | |
341 | + | |
342 | + do { | |
343 | + if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) | |
344 | + return 0; | |
345 | + | |
346 | + i++; | |
347 | + /* if locallity is set STS should not be 0xFF */ | |
348 | + } while ((buf == 0xFF) && i < 10); | |
349 | + | |
350 | + return buf; | |
291 | 351 | } |
292 | 352 | |
293 | 353 | static void tpm_tis_i2c_ready(struct tpm_chip *chip) |
... | ... | @@ -328,7 +388,7 @@ |
328 | 388 | |
329 | 389 | /* check current status */ |
330 | 390 | *status = tpm_tis_i2c_status(chip); |
331 | - if ((*status & mask) == mask) | |
391 | + if ((*status != 0xFF) && (*status & mask) == mask) | |
332 | 392 | return 0; |
333 | 393 | |
334 | 394 | stop = jiffies + timeout; |
... | ... | @@ -372,7 +432,6 @@ |
372 | 432 | /* avoid endless loop in case of broken HW */ |
373 | 433 | if (retries > MAX_COUNT_LONG) |
374 | 434 | return -EIO; |
375 | - | |
376 | 435 | } |
377 | 436 | return size; |
378 | 437 | } |
... | ... | @@ -480,7 +539,6 @@ |
480 | 539 | rc = -EIO; |
481 | 540 | goto out_err; |
482 | 541 | } |
483 | - | |
484 | 542 | } |
485 | 543 | |
486 | 544 | /* write last byte */ |
... | ... | @@ -568,6 +626,7 @@ |
568 | 626 | |
569 | 627 | chip = tpm_register_hardware(dev, &tpm_tis_i2c); |
570 | 628 | if (!chip) { |
629 | + dev_err(dev, "could not register hardware\n"); | |
571 | 630 | rc = -ENODEV; |
572 | 631 | goto out_err; |
573 | 632 | } |
574 | 633 | |
575 | 634 | |
... | ... | @@ -582,20 +641,24 @@ |
582 | 641 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
583 | 642 | |
584 | 643 | if (request_locality(chip, 0) != 0) { |
644 | + dev_err(dev, "could not request locality\n"); | |
585 | 645 | rc = -ENODEV; |
586 | 646 | goto out_vendor; |
587 | 647 | } |
588 | 648 | |
589 | 649 | /* read four bytes from DID_VID register */ |
590 | 650 | if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { |
651 | + dev_err(dev, "could not read vendor id\n"); | |
591 | 652 | rc = -EIO; |
592 | 653 | goto out_release; |
593 | 654 | } |
594 | 655 | |
595 | - /* create DID_VID register value, after swapping to little-endian */ | |
596 | - vendor = be32_to_cpu((__be32) vendor); | |
597 | - | |
598 | - if (vendor != TPM_TIS_I2C_DID_VID) { | |
656 | + if (vendor == TPM_TIS_I2C_DID_VID_9645) { | |
657 | + tpm_dev.chip_type = SLB9645; | |
658 | + } else if (vendor == TPM_TIS_I2C_DID_VID_9635) { | |
659 | + tpm_dev.chip_type = SLB9635; | |
660 | + } else { | |
661 | + dev_err(dev, "vendor id did not match! ID was %08x\n", vendor); | |
599 | 662 | rc = -ENODEV; |
600 | 663 | goto out_release; |
601 | 664 | } |
602 | 665 | |
603 | 666 | |
604 | 667 | |
605 | 668 | |
... | ... | @@ -631,22 +694,53 @@ |
631 | 694 | |
632 | 695 | static const struct i2c_device_id tpm_tis_i2c_table[] = { |
633 | 696 | {"tpm_i2c_infineon", 0}, |
697 | + {"slb9635tt", 0}, | |
698 | + {"slb9645tt", 1}, | |
634 | 699 | {}, |
635 | 700 | }; |
636 | 701 | |
637 | 702 | MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); |
703 | + | |
704 | +#ifdef CONFIG_OF | |
705 | +static const struct of_device_id tpm_tis_i2c_of_match[] = { | |
706 | + { | |
707 | + .name = "tpm_i2c_infineon", | |
708 | + .type = "tpm", | |
709 | + .compatible = "infineon,tpm_i2c_infineon", | |
710 | + .data = (void *)0 | |
711 | + }, | |
712 | + { | |
713 | + .name = "slb9635tt", | |
714 | + .type = "tpm", | |
715 | + .compatible = "infineon,slb9635tt", | |
716 | + .data = (void *)0 | |
717 | + }, | |
718 | + { | |
719 | + .name = "slb9645tt", | |
720 | + .type = "tpm", | |
721 | + .compatible = "infineon,slb9645tt", | |
722 | + .data = (void *)1 | |
723 | + }, | |
724 | + {}, | |
725 | +}; | |
726 | +MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); | |
727 | +#endif | |
728 | + | |
638 | 729 | static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); |
639 | 730 | |
640 | 731 | static int tpm_tis_i2c_probe(struct i2c_client *client, |
641 | 732 | const struct i2c_device_id *id) |
642 | 733 | { |
643 | 734 | int rc; |
644 | - if (tpm_dev.client != NULL) | |
735 | + struct device *dev = &(client->dev); | |
736 | + | |
737 | + if (tpm_dev.client != NULL) { | |
738 | + dev_err(dev, "This driver only supports one client at a time\n"); | |
645 | 739 | return -EBUSY; /* We only support one client */ |
740 | + } | |
646 | 741 | |
647 | 742 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
648 | - dev_err(&client->dev, | |
649 | - "no algorithms associated to the i2c bus\n"); | |
743 | + dev_err(dev, "no algorithms associated to the i2c bus\n"); | |
650 | 744 | return -ENODEV; |
651 | 745 | } |
652 | 746 | |
... | ... | @@ -682,7 +776,6 @@ |
682 | 776 | } |
683 | 777 | |
684 | 778 | static struct i2c_driver tpm_tis_i2c_driver = { |
685 | - | |
686 | 779 | .id_table = tpm_tis_i2c_table, |
687 | 780 | .probe = tpm_tis_i2c_probe, |
688 | 781 | .remove = tpm_tis_i2c_remove, |
689 | 782 | |
... | ... | @@ -690,12 +783,13 @@ |
690 | 783 | .name = "tpm_i2c_infineon", |
691 | 784 | .owner = THIS_MODULE, |
692 | 785 | .pm = &tpm_tis_i2c_ops, |
786 | + .of_match_table = of_match_ptr(tpm_tis_i2c_of_match), | |
693 | 787 | }, |
694 | 788 | }; |
695 | 789 | |
696 | 790 | module_i2c_driver(tpm_tis_i2c_driver); |
697 | 791 | MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); |
698 | 792 | MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); |
699 | -MODULE_VERSION("2.1.5"); | |
793 | +MODULE_VERSION("2.2.0"); | |
700 | 794 | MODULE_LICENSE("GPL"); |
drivers/char/tpm/tpm_i2c_stm_st33.c
... | ... | @@ -36,7 +36,6 @@ |
36 | 36 | #include <linux/i2c.h> |
37 | 37 | #include <linux/fs.h> |
38 | 38 | #include <linux/miscdevice.h> |
39 | -#include <linux/module.h> | |
40 | 39 | #include <linux/kernel.h> |
41 | 40 | #include <linux/delay.h> |
42 | 41 | #include <linux/init.h> |
... | ... | @@ -50,7 +49,6 @@ |
50 | 49 | #include <linux/uaccess.h> |
51 | 50 | #include <linux/io.h> |
52 | 51 | #include <linux/slab.h> |
53 | -#include <linux/sched.h> | |
54 | 52 | |
55 | 53 | #include "tpm.h" |
56 | 54 | #include "tpm_i2c_stm_st33.h" |
... | ... | @@ -178,7 +176,7 @@ |
178 | 176 | struct i2c_client *client; |
179 | 177 | struct st33zp24_platform_data *pin_infos; |
180 | 178 | |
181 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
179 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
182 | 180 | pin_infos = client->dev.platform_data; |
183 | 181 | |
184 | 182 | status = wait_for_completion_interruptible_timeout( |
185 | 183 | |
... | ... | @@ -197,12 +195,12 @@ |
197 | 195 | int status = 2; |
198 | 196 | struct i2c_client *client; |
199 | 197 | |
200 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
198 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
201 | 199 | |
202 | 200 | status = _wait_for_interrupt_serirq_timeout(chip, timeout); |
203 | 201 | if (!status) { |
204 | 202 | status = -EBUSY; |
205 | - } else{ | |
203 | + } else { | |
206 | 204 | clear_interruption(client); |
207 | 205 | if (condition) |
208 | 206 | status = 1; |
... | ... | @@ -219,7 +217,7 @@ |
219 | 217 | struct i2c_client *client; |
220 | 218 | u8 data; |
221 | 219 | |
222 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
220 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
223 | 221 | |
224 | 222 | data = TPM_STS_COMMAND_READY; |
225 | 223 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); |
... | ... | @@ -236,7 +234,7 @@ |
236 | 234 | { |
237 | 235 | struct i2c_client *client; |
238 | 236 | u8 data; |
239 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
237 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
240 | 238 | |
241 | 239 | I2C_READ_DATA(client, TPM_STS, &data, 1); |
242 | 240 | return data; |
... | ... | @@ -254,7 +252,7 @@ |
254 | 252 | u8 data; |
255 | 253 | u8 status; |
256 | 254 | |
257 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
255 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
258 | 256 | |
259 | 257 | status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); |
260 | 258 | if (status && (data & |
... | ... | @@ -278,7 +276,7 @@ |
278 | 276 | struct i2c_client *client; |
279 | 277 | u8 data; |
280 | 278 | |
281 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
279 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
282 | 280 | |
283 | 281 | if (check_locality(chip) == chip->vendor.locality) |
284 | 282 | return chip->vendor.locality; |
... | ... | @@ -294,7 +292,7 @@ |
294 | 292 | chip->vendor.timeout_a); |
295 | 293 | if (rc > 0) |
296 | 294 | return chip->vendor.locality; |
297 | - } else{ | |
295 | + } else { | |
298 | 296 | stop = jiffies + chip->vendor.timeout_a; |
299 | 297 | do { |
300 | 298 | if (check_locality(chip) >= 0) |
... | ... | @@ -316,7 +314,7 @@ |
316 | 314 | struct i2c_client *client; |
317 | 315 | u8 data; |
318 | 316 | |
319 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
317 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
320 | 318 | data = TPM_ACCESS_ACTIVE_LOCALITY; |
321 | 319 | |
322 | 320 | I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); |
... | ... | @@ -333,7 +331,7 @@ |
333 | 331 | int burstcnt, status; |
334 | 332 | u8 tpm_reg, temp; |
335 | 333 | |
336 | - struct i2c_client *client = (struct i2c_client *) TPM_VPRIV(chip); | |
334 | + struct i2c_client *client = (struct i2c_client *)TPM_VPRIV(chip); | |
337 | 335 | |
338 | 336 | stop = jiffies + chip->vendor.timeout_d; |
339 | 337 | do { |
... | ... | @@ -379,7 +377,7 @@ |
379 | 377 | mask), timeout); |
380 | 378 | if (rc > 0) |
381 | 379 | return 0; |
382 | - } else{ | |
380 | + } else { | |
383 | 381 | stop = jiffies + timeout; |
384 | 382 | do { |
385 | 383 | msleep(TPM_TIMEOUT); |
... | ... | @@ -403,7 +401,7 @@ |
403 | 401 | int size = 0, burstcnt, len; |
404 | 402 | struct i2c_client *client; |
405 | 403 | |
406 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
404 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
407 | 405 | |
408 | 406 | while (size < count && |
409 | 407 | wait_for_stat(chip, |
... | ... | @@ -433,7 +431,7 @@ |
433 | 431 | |
434 | 432 | disable_irq_nosync(irq); |
435 | 433 | |
436 | - client = (struct i2c_client *) TPM_VPRIV(chip); | |
434 | + client = (struct i2c_client *)TPM_VPRIV(chip); | |
437 | 435 | pin_infos = client->dev.platform_data; |
438 | 436 | |
439 | 437 | complete(&pin_infos->irq_detection); |
... | ... | @@ -453,8 +451,7 @@ |
453 | 451 | static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, |
454 | 452 | size_t len) |
455 | 453 | { |
456 | - u32 status, | |
457 | - burstcnt = 0, i, size; | |
454 | + u32 status, burstcnt = 0, i, size; | |
458 | 455 | int ret; |
459 | 456 | u8 data; |
460 | 457 | struct i2c_client *client; |
... | ... | @@ -483,7 +480,7 @@ |
483 | 480 | } |
484 | 481 | } |
485 | 482 | |
486 | - for (i = 0 ; i < len - 1 ;) { | |
483 | + for (i = 0; i < len - 1;) { | |
487 | 484 | burstcnt = get_burstcount(chip); |
488 | 485 | size = min_t(int, len - i - 1, burstcnt); |
489 | 486 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); |
... | ... | @@ -547,7 +544,7 @@ |
547 | 544 | goto out; |
548 | 545 | } |
549 | 546 | |
550 | - expected = be32_to_cpu(*(__be32 *) (buf + 2)); | |
547 | + expected = be32_to_cpu(*(__be32 *)(buf + 2)); | |
551 | 548 | if (expected > count) { |
552 | 549 | size = -EIO; |
553 | 550 | goto out; |
... | ... | @@ -569,7 +566,7 @@ |
569 | 566 | |
570 | 567 | static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status) |
571 | 568 | { |
572 | - return (status == TPM_STS_COMMAND_READY); | |
569 | + return (status == TPM_STS_COMMAND_READY); | |
573 | 570 | } |
574 | 571 | |
575 | 572 | static const struct file_operations tpm_st33_i2c_fops = { |
... | ... | @@ -617,7 +614,7 @@ |
617 | 614 | .miscdev = {.fops = &tpm_st33_i2c_fops,}, |
618 | 615 | }; |
619 | 616 | |
620 | -static int interrupts ; | |
617 | +static int interrupts; | |
621 | 618 | module_param(interrupts, int, 0444); |
622 | 619 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
623 | 620 | |
... | ... | @@ -714,7 +711,7 @@ |
714 | 711 | "TPM SERIRQ management", chip); |
715 | 712 | if (err < 0) { |
716 | 713 | dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", |
717 | - gpio_to_irq(platform_data->io_serirq)); | |
714 | + gpio_to_irq(platform_data->io_serirq)); | |
718 | 715 | goto _irq_set; |
719 | 716 | } |
720 | 717 | |
... | ... | @@ -754,7 +751,7 @@ |
754 | 751 | dev_info(chip->dev, "TPM I2C Initialized\n"); |
755 | 752 | return 0; |
756 | 753 | _irq_set: |
757 | - free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip); | |
754 | + free_irq(gpio_to_irq(platform_data->io_serirq), (void *)chip); | |
758 | 755 | _gpio_init2: |
759 | 756 | if (interrupts) |
760 | 757 | gpio_free(platform_data->io_serirq); |
... | ... | @@ -784,7 +781,7 @@ |
784 | 781 | { |
785 | 782 | struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); |
786 | 783 | struct st33zp24_platform_data *pin_infos = |
787 | - ((struct i2c_client *) TPM_VPRIV(chip))->dev.platform_data; | |
784 | + ((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data; | |
788 | 785 | |
789 | 786 | if (pin_infos != NULL) { |
790 | 787 | free_irq(pin_infos->io_serirq, chip); |
791 | 788 | |
... | ... | @@ -823,9 +820,9 @@ |
823 | 820 | struct st33zp24_platform_data *pin_infos = dev->platform_data; |
824 | 821 | int ret = 0; |
825 | 822 | |
826 | - if (power_mgt) | |
823 | + if (power_mgt) { | |
827 | 824 | gpio_set_value(pin_infos->io_lpcpd, 0); |
828 | - else{ | |
825 | + } else { | |
829 | 826 | if (chip->data_buffer == NULL) |
830 | 827 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; |
831 | 828 | ret = tpm_pm_suspend(dev); |
... | ... | @@ -851,12 +848,12 @@ |
851 | 848 | (chip->vendor.status(chip) & |
852 | 849 | TPM_STS_VALID) == TPM_STS_VALID, |
853 | 850 | chip->vendor.timeout_b); |
854 | - } else{ | |
855 | - if (chip->data_buffer == NULL) | |
856 | - chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | |
857 | - ret = tpm_pm_resume(dev); | |
858 | - if (!ret) | |
859 | - tpm_do_selftest(chip); | |
851 | + } else { | |
852 | + if (chip->data_buffer == NULL) | |
853 | + chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | |
854 | + ret = tpm_pm_resume(dev); | |
855 | + if (!ret) | |
856 | + tpm_do_selftest(chip); | |
860 | 857 | } |
861 | 858 | return ret; |
862 | 859 | } /* tpm_st33_i2c_pm_resume() */ |
... | ... | @@ -867,7 +864,8 @@ |
867 | 864 | {} |
868 | 865 | }; |
869 | 866 | MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id); |
870 | -static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume); | |
867 | +static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, | |
868 | + tpm_st33_i2c_pm_resume); | |
871 | 869 | static struct i2c_driver tpm_st33_i2c_driver = { |
872 | 870 | .driver = { |
873 | 871 | .owner = THIS_MODULE, |
drivers/char/tpm/tpm_ppi.c
... | ... | @@ -158,9 +158,9 @@ |
158 | 158 | ACPI_TYPE_STRING); |
159 | 159 | if (ACPI_FAILURE(status)) |
160 | 160 | return -ENOMEM; |
161 | - strncpy(version, | |
161 | + strlcpy(version, | |
162 | 162 | ((union acpi_object *)output.pointer)->string.pointer, |
163 | - PPI_VERSION_LEN); | |
163 | + PPI_VERSION_LEN + 1); | |
164 | 164 | kfree(output.pointer); |
165 | 165 | output.length = ACPI_ALLOCATE_BUFFER; |
166 | 166 | output.pointer = NULL; |
167 | 167 | |
... | ... | @@ -237,9 +237,9 @@ |
237 | 237 | ACPI_TYPE_STRING); |
238 | 238 | if (ACPI_FAILURE(status)) |
239 | 239 | return -ENOMEM; |
240 | - strncpy(version, | |
240 | + strlcpy(version, | |
241 | 241 | ((union acpi_object *)output.pointer)->string.pointer, |
242 | - PPI_VERSION_LEN); | |
242 | + PPI_VERSION_LEN + 1); | |
243 | 243 | /* |
244 | 244 | * PPI spec defines params[3].type as empty package, but some platforms |
245 | 245 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for |
... | ... | @@ -351,7 +351,7 @@ |
351 | 351 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) |
352 | 352 | { |
353 | 353 | char *str = buf; |
354 | - char version[PPI_VERSION_LEN]; | |
354 | + char version[PPI_VERSION_LEN + 1]; | |
355 | 355 | acpi_handle handle; |
356 | 356 | acpi_status status; |
357 | 357 | struct acpi_object_list input; |
358 | 358 | |
... | ... | @@ -381,9 +381,9 @@ |
381 | 381 | if (ACPI_FAILURE(status)) |
382 | 382 | return -ENOMEM; |
383 | 383 | |
384 | - strncpy(version, | |
384 | + strlcpy(version, | |
385 | 385 | ((union acpi_object *)output.pointer)->string.pointer, |
386 | - PPI_VERSION_LEN); | |
386 | + PPI_VERSION_LEN + 1); | |
387 | 387 | kfree(output.pointer); |
388 | 388 | output.length = ACPI_ALLOCATE_BUFFER; |
389 | 389 | output.pointer = NULL; |
fs/nfs/super.c
... | ... | @@ -2385,10 +2385,9 @@ |
2385 | 2385 | struct nfs_mount_info *mount_info) |
2386 | 2386 | { |
2387 | 2387 | /* clone any lsm security options from the parent to the new sb */ |
2388 | - security_sb_clone_mnt_opts(mount_info->cloned->sb, s); | |
2389 | 2388 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) |
2390 | 2389 | return -ESTALE; |
2391 | - return 0; | |
2390 | + return security_sb_clone_mnt_opts(mount_info->cloned->sb, s); | |
2392 | 2391 | } |
2393 | 2392 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); |
2394 | 2393 |
include/linux/security.h
... | ... | @@ -1440,7 +1440,7 @@ |
1440 | 1440 | struct path *new_path); |
1441 | 1441 | int (*sb_set_mnt_opts) (struct super_block *sb, |
1442 | 1442 | struct security_mnt_opts *opts); |
1443 | - void (*sb_clone_mnt_opts) (const struct super_block *oldsb, | |
1443 | + int (*sb_clone_mnt_opts) (const struct super_block *oldsb, | |
1444 | 1444 | struct super_block *newsb); |
1445 | 1445 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
1446 | 1446 | |
... | ... | @@ -1726,7 +1726,7 @@ |
1726 | 1726 | int security_sb_umount(struct vfsmount *mnt, int flags); |
1727 | 1727 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
1728 | 1728 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); |
1729 | -void security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
1729 | +int security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
1730 | 1730 | struct super_block *newsb); |
1731 | 1731 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
1732 | 1732 | |
1733 | 1733 | |
... | ... | @@ -2016,9 +2016,11 @@ |
2016 | 2016 | return 0; |
2017 | 2017 | } |
2018 | 2018 | |
2019 | -static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
2019 | +static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
2020 | 2020 | struct super_block *newsb) |
2021 | -{ } | |
2021 | +{ | |
2022 | + return 0; | |
2023 | +} | |
2022 | 2024 | |
2023 | 2025 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
2024 | 2026 | { |
include/uapi/linux/magic.h
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | #define DEBUGFS_MAGIC 0x64626720 |
12 | 12 | #define SECURITYFS_MAGIC 0x73636673 |
13 | 13 | #define SELINUX_MAGIC 0xf97cff8c |
14 | +#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ | |
14 | 15 | #define RAMFS_MAGIC 0x858458f6 /* some random number */ |
15 | 16 | #define TMPFS_MAGIC 0x01021994 |
16 | 17 | #define HUGETLBFS_MAGIC 0x958458f6 /* some random number */ |
kernel/seccomp.c
security/capability.c
... | ... | @@ -98,9 +98,10 @@ |
98 | 98 | return 0; |
99 | 99 | } |
100 | 100 | |
101 | -static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, | |
101 | +static int cap_sb_clone_mnt_opts(const struct super_block *oldsb, | |
102 | 102 | struct super_block *newsb) |
103 | 103 | { |
104 | + return 0; | |
104 | 105 | } |
105 | 106 | |
106 | 107 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
security/integrity/ima/ima_main.c
... | ... | @@ -189,11 +189,9 @@ |
189 | 189 | if (rc != 0) |
190 | 190 | goto out_digsig; |
191 | 191 | |
192 | - if (function != BPRM_CHECK) | |
193 | - pathname = ima_d_path(&file->f_path, &pathbuf); | |
194 | - | |
192 | + pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename; | |
195 | 193 | if (!pathname) |
196 | - pathname = filename; | |
194 | + pathname = (const char *)file->f_dentry->d_name.name; | |
197 | 195 | |
198 | 196 | if (action & IMA_MEASURE) |
199 | 197 | ima_store_measurement(iint, file, pathname); |
... | ... | @@ -226,8 +224,7 @@ |
226 | 224 | int ima_file_mmap(struct file *file, unsigned long prot) |
227 | 225 | { |
228 | 226 | if (file && (prot & PROT_EXEC)) |
229 | - return process_measurement(file, file->f_dentry->d_name.name, | |
230 | - MAY_EXEC, MMAP_CHECK); | |
227 | + return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK); | |
231 | 228 | return 0; |
232 | 229 | } |
233 | 230 | |
... | ... | @@ -265,7 +262,7 @@ |
265 | 262 | int ima_file_check(struct file *file, int mask) |
266 | 263 | { |
267 | 264 | ima_rdwr_violation_check(file); |
268 | - return process_measurement(file, file->f_dentry->d_name.name, | |
265 | + return process_measurement(file, NULL, | |
269 | 266 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
270 | 267 | FILE_CHECK); |
271 | 268 | } |
... | ... | @@ -290,8 +287,7 @@ |
290 | 287 | #endif |
291 | 288 | return 0; /* We rely on module signature checking */ |
292 | 289 | } |
293 | - return process_measurement(file, file->f_dentry->d_name.name, | |
294 | - MAY_EXEC, MODULE_CHECK); | |
290 | + return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); | |
295 | 291 | } |
296 | 292 | |
297 | 293 | static int __init init_ima(void) |
security/security.c
... | ... | @@ -299,10 +299,10 @@ |
299 | 299 | } |
300 | 300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
301 | 301 | |
302 | -void security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
302 | +int security_sb_clone_mnt_opts(const struct super_block *oldsb, | |
303 | 303 | struct super_block *newsb) |
304 | 304 | { |
305 | - security_ops->sb_clone_mnt_opts(oldsb, newsb); | |
305 | + return security_ops->sb_clone_mnt_opts(oldsb, newsb); | |
306 | 306 | } |
307 | 307 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
308 | 308 |
security/selinux/hooks.c
... | ... | @@ -751,7 +751,37 @@ |
751 | 751 | goto out; |
752 | 752 | } |
753 | 753 | |
754 | -static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |
754 | +static int selinux_cmp_sb_context(const struct super_block *oldsb, | |
755 | + const struct super_block *newsb) | |
756 | +{ | |
757 | + struct superblock_security_struct *old = oldsb->s_security; | |
758 | + struct superblock_security_struct *new = newsb->s_security; | |
759 | + char oldflags = old->flags & SE_MNTMASK; | |
760 | + char newflags = new->flags & SE_MNTMASK; | |
761 | + | |
762 | + if (oldflags != newflags) | |
763 | + goto mismatch; | |
764 | + if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid) | |
765 | + goto mismatch; | |
766 | + if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid) | |
767 | + goto mismatch; | |
768 | + if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid) | |
769 | + goto mismatch; | |
770 | + if (oldflags & ROOTCONTEXT_MNT) { | |
771 | + struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security; | |
772 | + struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security; | |
773 | + if (oldroot->sid != newroot->sid) | |
774 | + goto mismatch; | |
775 | + } | |
776 | + return 0; | |
777 | +mismatch: | |
778 | + printk(KERN_WARNING "SELinux: mount invalid. Same superblock, " | |
779 | + "different security settings for (dev %s, " | |
780 | + "type %s)\n", newsb->s_id, newsb->s_type->name); | |
781 | + return -EBUSY; | |
782 | +} | |
783 | + | |
784 | +static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |
755 | 785 | struct super_block *newsb) |
756 | 786 | { |
757 | 787 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; |
758 | 788 | |
759 | 789 | |
... | ... | @@ -766,14 +796,14 @@ |
766 | 796 | * mount options. thus we can safely deal with this superblock later |
767 | 797 | */ |
768 | 798 | if (!ss_initialized) |
769 | - return; | |
799 | + return 0; | |
770 | 800 | |
771 | 801 | /* how can we clone if the old one wasn't set up?? */ |
772 | 802 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
773 | 803 | |
774 | - /* if fs is reusing a sb, just let its options stand... */ | |
804 | + /* if fs is reusing a sb, make sure that the contexts match */ | |
775 | 805 | if (newsbsec->flags & SE_SBINITIALIZED) |
776 | - return; | |
806 | + return selinux_cmp_sb_context(oldsb, newsb); | |
777 | 807 | |
778 | 808 | mutex_lock(&newsbsec->lock); |
779 | 809 | |
... | ... | @@ -806,6 +836,7 @@ |
806 | 836 | |
807 | 837 | sb_finish_set_opts(newsb); |
808 | 838 | mutex_unlock(&newsbsec->lock); |
839 | + return 0; | |
809 | 840 | } |
810 | 841 | |
811 | 842 | static int selinux_parse_opts_str(char *options, |
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
... | ... | @@ -654,7 +654,7 @@ |
654 | 654 | /* |
655 | 655 | * You also need write access to the containing directory |
656 | 656 | */ |
657 | - smk_ad_setfield_u_fs_path_dentry(&ad, NULL); | |
657 | + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | |
658 | 658 | smk_ad_setfield_u_fs_inode(&ad, dir); |
659 | 659 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
660 | 660 | } |
... | ... | @@ -685,7 +685,7 @@ |
685 | 685 | /* |
686 | 686 | * You also need write access to the containing directory |
687 | 687 | */ |
688 | - smk_ad_setfield_u_fs_path_dentry(&ad, NULL); | |
688 | + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | |
689 | 689 | smk_ad_setfield_u_fs_inode(&ad, dir); |
690 | 690 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
691 | 691 | } |
security/smack/smackfs.c
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #include <linux/seq_file.h> |
27 | 27 | #include <linux/ctype.h> |
28 | 28 | #include <linux/audit.h> |
29 | +#include <linux/magic.h> | |
29 | 30 | #include "smack.h" |
30 | 31 | |
31 | 32 | /* |
32 | 33 | |
... | ... | @@ -50,12 +51,12 @@ |
50 | 51 | SMK_ACCESS2 = 16, /* make an access check with long labels */ |
51 | 52 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ |
52 | 53 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ |
54 | + SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ | |
53 | 55 | }; |
54 | 56 | |
55 | 57 | /* |
56 | 58 | * List locks |
57 | 59 | */ |
58 | -static DEFINE_MUTEX(smack_list_lock); | |
59 | 60 | static DEFINE_MUTEX(smack_cipso_lock); |
60 | 61 | static DEFINE_MUTEX(smack_ambient_lock); |
61 | 62 | static DEFINE_MUTEX(smk_netlbladdr_lock); |
... | ... | @@ -110,6 +111,13 @@ |
110 | 111 | |
111 | 112 | LIST_HEAD(smack_rule_list); |
112 | 113 | |
114 | +struct smack_parsed_rule { | |
115 | + char *smk_subject; | |
116 | + char *smk_object; | |
117 | + int smk_access1; | |
118 | + int smk_access2; | |
119 | +}; | |
120 | + | |
113 | 121 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
114 | 122 | |
115 | 123 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; |
116 | 124 | |
117 | 125 | |
118 | 126 | |
119 | 127 | |
120 | 128 | |
... | ... | @@ -167,25 +175,28 @@ |
167 | 175 | #define SMK_NETLBLADDRMIN 9 |
168 | 176 | |
169 | 177 | /** |
170 | - * smk_set_access - add a rule to the rule list | |
171 | - * @srp: the new rule to add | |
178 | + * smk_set_access - add a rule to the rule list or replace an old rule | |
179 | + * @srp: the rule to add or replace | |
172 | 180 | * @rule_list: the list of rules |
173 | 181 | * @rule_lock: the rule list lock |
182 | + * @global: if non-zero, indicates a global rule | |
174 | 183 | * |
175 | 184 | * Looks through the current subject/object/access list for |
176 | 185 | * the subject/object pair and replaces the access that was |
177 | 186 | * there. If the pair isn't found add it with the specified |
178 | 187 | * access. |
179 | 188 | * |
180 | - * Returns 1 if a rule was found to exist already, 0 if it is new | |
181 | 189 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails |
182 | 190 | * during the allocation of the new pair to add. |
183 | 191 | */ |
184 | -static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |
185 | - struct mutex *rule_lock) | |
192 | +static int smk_set_access(struct smack_parsed_rule *srp, | |
193 | + struct list_head *rule_list, | |
194 | + struct mutex *rule_lock, int global) | |
186 | 195 | { |
187 | 196 | struct smack_rule *sp; |
197 | + struct smack_master_list *smlp; | |
188 | 198 | int found = 0; |
199 | + int rc = 0; | |
189 | 200 | |
190 | 201 | mutex_lock(rule_lock); |
191 | 202 | |
192 | 203 | |
193 | 204 | |
194 | 205 | |
195 | 206 | |
196 | 207 | |
... | ... | @@ -197,23 +208,89 @@ |
197 | 208 | if (sp->smk_object == srp->smk_object && |
198 | 209 | sp->smk_subject == srp->smk_subject) { |
199 | 210 | found = 1; |
200 | - sp->smk_access = srp->smk_access; | |
211 | + sp->smk_access |= srp->smk_access1; | |
212 | + sp->smk_access &= ~srp->smk_access2; | |
201 | 213 | break; |
202 | 214 | } |
203 | 215 | } |
204 | - if (found == 0) | |
205 | - list_add_rcu(&srp->list, rule_list); | |
206 | 216 | |
217 | + if (found == 0) { | |
218 | + sp = kzalloc(sizeof(*sp), GFP_KERNEL); | |
219 | + if (sp == NULL) { | |
220 | + rc = -ENOMEM; | |
221 | + goto out; | |
222 | + } | |
223 | + | |
224 | + sp->smk_subject = srp->smk_subject; | |
225 | + sp->smk_object = srp->smk_object; | |
226 | + sp->smk_access = srp->smk_access1 & ~srp->smk_access2; | |
227 | + | |
228 | + list_add_rcu(&sp->list, rule_list); | |
229 | + /* | |
230 | + * If this is a global as opposed to self and a new rule | |
231 | + * it needs to get added for reporting. | |
232 | + */ | |
233 | + if (global) { | |
234 | + smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); | |
235 | + if (smlp != NULL) { | |
236 | + smlp->smk_rule = sp; | |
237 | + list_add_rcu(&smlp->list, &smack_rule_list); | |
238 | + } else | |
239 | + rc = -ENOMEM; | |
240 | + } | |
241 | + } | |
242 | + | |
243 | +out: | |
207 | 244 | mutex_unlock(rule_lock); |
245 | + return rc; | |
246 | +} | |
208 | 247 | |
209 | - return found; | |
248 | +/** | |
249 | + * smk_perm_from_str - parse smack accesses from a text string | |
250 | + * @string: a text string that contains a Smack accesses code | |
251 | + * | |
252 | + * Returns an integer with respective bits set for specified accesses. | |
253 | + */ | |
254 | +static int smk_perm_from_str(const char *string) | |
255 | +{ | |
256 | + int perm = 0; | |
257 | + const char *cp; | |
258 | + | |
259 | + for (cp = string; ; cp++) | |
260 | + switch (*cp) { | |
261 | + case '-': | |
262 | + break; | |
263 | + case 'r': | |
264 | + case 'R': | |
265 | + perm |= MAY_READ; | |
266 | + break; | |
267 | + case 'w': | |
268 | + case 'W': | |
269 | + perm |= MAY_WRITE; | |
270 | + break; | |
271 | + case 'x': | |
272 | + case 'X': | |
273 | + perm |= MAY_EXEC; | |
274 | + break; | |
275 | + case 'a': | |
276 | + case 'A': | |
277 | + perm |= MAY_APPEND; | |
278 | + break; | |
279 | + case 't': | |
280 | + case 'T': | |
281 | + perm |= MAY_TRANSMUTE; | |
282 | + break; | |
283 | + default: | |
284 | + return perm; | |
285 | + } | |
210 | 286 | } |
211 | 287 | |
212 | 288 | /** |
213 | 289 | * smk_fill_rule - Fill Smack rule from strings |
214 | 290 | * @subject: subject label string |
215 | 291 | * @object: object label string |
216 | - * @access: access string | |
292 | + * @access1: access string | |
293 | + * @access2: string with permissions to be removed | |
217 | 294 | * @rule: Smack rule |
218 | 295 | * @import: if non-zero, import labels |
219 | 296 | * @len: label length limit |
... | ... | @@ -221,8 +298,9 @@ |
221 | 298 | * Returns 0 on success, -1 on failure |
222 | 299 | */ |
223 | 300 | static int smk_fill_rule(const char *subject, const char *object, |
224 | - const char *access, struct smack_rule *rule, | |
225 | - int import, int len) | |
301 | + const char *access1, const char *access2, | |
302 | + struct smack_parsed_rule *rule, int import, | |
303 | + int len) | |
226 | 304 | { |
227 | 305 | const char *cp; |
228 | 306 | struct smack_known *skp; |
229 | 307 | |
... | ... | @@ -255,37 +333,12 @@ |
255 | 333 | rule->smk_object = skp->smk_known; |
256 | 334 | } |
257 | 335 | |
258 | - rule->smk_access = 0; | |
336 | + rule->smk_access1 = smk_perm_from_str(access1); | |
337 | + if (access2) | |
338 | + rule->smk_access2 = smk_perm_from_str(access2); | |
339 | + else | |
340 | + rule->smk_access2 = ~rule->smk_access1; | |
259 | 341 | |
260 | - for (cp = access; *cp != '\0'; cp++) { | |
261 | - switch (*cp) { | |
262 | - case '-': | |
263 | - break; | |
264 | - case 'r': | |
265 | - case 'R': | |
266 | - rule->smk_access |= MAY_READ; | |
267 | - break; | |
268 | - case 'w': | |
269 | - case 'W': | |
270 | - rule->smk_access |= MAY_WRITE; | |
271 | - break; | |
272 | - case 'x': | |
273 | - case 'X': | |
274 | - rule->smk_access |= MAY_EXEC; | |
275 | - break; | |
276 | - case 'a': | |
277 | - case 'A': | |
278 | - rule->smk_access |= MAY_APPEND; | |
279 | - break; | |
280 | - case 't': | |
281 | - case 'T': | |
282 | - rule->smk_access |= MAY_TRANSMUTE; | |
283 | - break; | |
284 | - default: | |
285 | - return 0; | |
286 | - } | |
287 | - } | |
288 | - | |
289 | 342 | return 0; |
290 | 343 | } |
291 | 344 | |
292 | 345 | |
293 | 346 | |
294 | 347 | |
295 | 348 | |
296 | 349 | |
... | ... | @@ -297,30 +350,33 @@ |
297 | 350 | * |
298 | 351 | * Returns 0 on success, -1 on errors. |
299 | 352 | */ |
300 | -static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) | |
353 | +static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule, | |
354 | + int import) | |
301 | 355 | { |
302 | 356 | int rc; |
303 | 357 | |
304 | 358 | rc = smk_fill_rule(data, data + SMK_LABELLEN, |
305 | - data + SMK_LABELLEN + SMK_LABELLEN, rule, import, | |
306 | - SMK_LABELLEN); | |
359 | + data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule, | |
360 | + import, SMK_LABELLEN); | |
307 | 361 | return rc; |
308 | 362 | } |
309 | 363 | |
310 | 364 | /** |
311 | 365 | * smk_parse_long_rule - parse Smack rule from rule string |
312 | 366 | * @data: string to be parsed, null terminated |
313 | - * @rule: Smack rule | |
367 | + * @rule: Will be filled with Smack parsed rule | |
314 | 368 | * @import: if non-zero, import labels |
369 | + * @change: if non-zero, data is from /smack/change-rule | |
315 | 370 | * |
316 | 371 | * Returns 0 on success, -1 on failure |
317 | 372 | */ |
318 | -static int smk_parse_long_rule(const char *data, struct smack_rule *rule, | |
319 | - int import) | |
373 | +static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, | |
374 | + int import, int change) | |
320 | 375 | { |
321 | 376 | char *subject; |
322 | 377 | char *object; |
323 | - char *access; | |
378 | + char *access1; | |
379 | + char *access2; | |
324 | 380 | int datalen; |
325 | 381 | int rc = -1; |
326 | 382 | |
327 | 383 | |
328 | 384 | |
329 | 385 | |
... | ... | @@ -334,14 +390,27 @@ |
334 | 390 | object = kzalloc(datalen, GFP_KERNEL); |
335 | 391 | if (object == NULL) |
336 | 392 | goto free_out_s; |
337 | - access = kzalloc(datalen, GFP_KERNEL); | |
338 | - if (access == NULL) | |
393 | + access1 = kzalloc(datalen, GFP_KERNEL); | |
394 | + if (access1 == NULL) | |
339 | 395 | goto free_out_o; |
396 | + access2 = kzalloc(datalen, GFP_KERNEL); | |
397 | + if (access2 == NULL) | |
398 | + goto free_out_a; | |
340 | 399 | |
341 | - if (sscanf(data, "%s %s %s", subject, object, access) == 3) | |
342 | - rc = smk_fill_rule(subject, object, access, rule, import, 0); | |
400 | + if (change) { | |
401 | + if (sscanf(data, "%s %s %s %s", | |
402 | + subject, object, access1, access2) == 4) | |
403 | + rc = smk_fill_rule(subject, object, access1, access2, | |
404 | + rule, import, 0); | |
405 | + } else { | |
406 | + if (sscanf(data, "%s %s %s", subject, object, access1) == 3) | |
407 | + rc = smk_fill_rule(subject, object, access1, NULL, | |
408 | + rule, import, 0); | |
409 | + } | |
343 | 410 | |
344 | - kfree(access); | |
411 | + kfree(access2); | |
412 | +free_out_a: | |
413 | + kfree(access1); | |
345 | 414 | free_out_o: |
346 | 415 | kfree(object); |
347 | 416 | free_out_s: |
... | ... | @@ -351,6 +420,7 @@ |
351 | 420 | |
352 | 421 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ |
353 | 422 | #define SMK_LONG_FMT 1 /* Variable long label format */ |
423 | +#define SMK_CHANGE_FMT 2 /* Rule modification format */ | |
354 | 424 | /** |
355 | 425 | * smk_write_rules_list - write() for any /smack rule file |
356 | 426 | * @file: file pointer, not actually used |
357 | 427 | |
358 | 428 | |
359 | 429 | |
... | ... | @@ -359,22 +429,24 @@ |
359 | 429 | * @ppos: where to start - must be 0 |
360 | 430 | * @rule_list: the list of rules to write to |
361 | 431 | * @rule_lock: lock for the rule list |
362 | - * @format: /smack/load or /smack/load2 format. | |
432 | + * @format: /smack/load or /smack/load2 or /smack/change-rule format. | |
363 | 433 | * |
364 | 434 | * Get one smack access rule from above. |
365 | 435 | * The format for SMK_LONG_FMT is: |
366 | 436 | * "subject<whitespace>object<whitespace>access[<whitespace>...]" |
367 | 437 | * The format for SMK_FIXED24_FMT is exactly: |
368 | 438 | * "subject object rwxat" |
439 | + * The format for SMK_CHANGE_FMT is: | |
440 | + * "subject<whitespace>object<whitespace> | |
441 | + * acc_enable<whitespace>acc_disable[<whitespace>...]" | |
369 | 442 | */ |
370 | 443 | static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, |
371 | 444 | size_t count, loff_t *ppos, |
372 | 445 | struct list_head *rule_list, |
373 | 446 | struct mutex *rule_lock, int format) |
374 | 447 | { |
375 | - struct smack_master_list *smlp; | |
376 | 448 | struct smack_known *skp; |
377 | - struct smack_rule *rule; | |
449 | + struct smack_parsed_rule *rule; | |
378 | 450 | char *data; |
379 | 451 | int datalen; |
380 | 452 | int rc = -EINVAL; |
381 | 453 | |
... | ... | @@ -417,8 +489,12 @@ |
417 | 489 | * Be sure the data string is terminated. |
418 | 490 | */ |
419 | 491 | data[count] = '\0'; |
420 | - if (smk_parse_long_rule(data, rule, 1)) | |
492 | + if (smk_parse_long_rule(data, rule, 1, 0)) | |
421 | 493 | goto out_free_rule; |
494 | + } else if (format == SMK_CHANGE_FMT) { | |
495 | + data[count] = '\0'; | |
496 | + if (smk_parse_long_rule(data, rule, 1, 1)) | |
497 | + goto out_free_rule; | |
422 | 498 | } else { |
423 | 499 | /* |
424 | 500 | * More on the minor hack for backward compatibility |
... | ... | @@ -437,22 +513,9 @@ |
437 | 513 | rule_lock = &skp->smk_rules_lock; |
438 | 514 | } |
439 | 515 | |
440 | - rc = count; | |
441 | - /* | |
442 | - * If this is a global as opposed to self and a new rule | |
443 | - * it needs to get added for reporting. | |
444 | - * smk_set_access returns true if there was already a rule | |
445 | - * for the subject/object pair, and false if it was new. | |
446 | - */ | |
447 | - if (!smk_set_access(rule, rule_list, rule_lock)) { | |
448 | - if (load) { | |
449 | - smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); | |
450 | - if (smlp != NULL) { | |
451 | - smlp->smk_rule = rule; | |
452 | - list_add_rcu(&smlp->list, &smack_rule_list); | |
453 | - } else | |
454 | - rc = -ENOMEM; | |
455 | - } | |
516 | + rc = smk_set_access(rule, rule_list, rule_lock, load); | |
517 | + if (rc == 0) { | |
518 | + rc = count; | |
456 | 519 | goto out; |
457 | 520 | } |
458 | 521 | |
... | ... | @@ -1774,7 +1837,7 @@ |
1774 | 1837 | static ssize_t smk_user_access(struct file *file, const char __user *buf, |
1775 | 1838 | size_t count, loff_t *ppos, int format) |
1776 | 1839 | { |
1777 | - struct smack_rule rule; | |
1840 | + struct smack_parsed_rule rule; | |
1778 | 1841 | char *data; |
1779 | 1842 | char *cod; |
1780 | 1843 | int res; |
1781 | 1844 | |
... | ... | @@ -1796,14 +1859,14 @@ |
1796 | 1859 | return -ENOMEM; |
1797 | 1860 | memcpy(cod, data, count); |
1798 | 1861 | cod[count] = '\0'; |
1799 | - res = smk_parse_long_rule(cod, &rule, 0); | |
1862 | + res = smk_parse_long_rule(cod, &rule, 0, 0); | |
1800 | 1863 | kfree(cod); |
1801 | 1864 | } |
1802 | 1865 | |
1803 | 1866 | if (res) |
1804 | 1867 | return -EINVAL; |
1805 | 1868 | |
1806 | - res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, | |
1869 | + res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1, | |
1807 | 1870 | NULL); |
1808 | 1871 | data[0] = res == 0 ? '1' : '0'; |
1809 | 1872 | data[1] = '\0'; |
1810 | 1873 | |
... | ... | @@ -2035,10 +2098,8 @@ |
2035 | 2098 | } |
2036 | 2099 | |
2037 | 2100 | skp = smk_find_entry(cp); |
2038 | - if (skp == NULL) { | |
2039 | - rc = -EINVAL; | |
2101 | + if (skp == NULL) | |
2040 | 2102 | goto free_out; |
2041 | - } | |
2042 | 2103 | |
2043 | 2104 | rule_list = &skp->smk_rules; |
2044 | 2105 | rule_lock = &skp->smk_rules_lock; |
... | ... | @@ -2077,6 +2138,33 @@ |
2077 | 2138 | } |
2078 | 2139 | |
2079 | 2140 | /** |
2141 | + * smk_write_change_rule - write() for /smack/change-rule | |
2142 | + * @file: file pointer | |
2143 | + * @buf: data from user space | |
2144 | + * @count: bytes sent | |
2145 | + * @ppos: where to start - must be 0 | |
2146 | + */ | |
2147 | +static ssize_t smk_write_change_rule(struct file *file, const char __user *buf, | |
2148 | + size_t count, loff_t *ppos) | |
2149 | +{ | |
2150 | + /* | |
2151 | + * Must have privilege. | |
2152 | + */ | |
2153 | + if (!capable(CAP_MAC_ADMIN)) | |
2154 | + return -EPERM; | |
2155 | + | |
2156 | + return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | |
2157 | + SMK_CHANGE_FMT); | |
2158 | +} | |
2159 | + | |
2160 | +static const struct file_operations smk_change_rule_ops = { | |
2161 | + .write = smk_write_change_rule, | |
2162 | + .read = simple_transaction_read, | |
2163 | + .release = simple_transaction_release, | |
2164 | + .llseek = generic_file_llseek, | |
2165 | +}; | |
2166 | + | |
2167 | +/** | |
2080 | 2168 | * smk_fill_super - fill the /smackfs superblock |
2081 | 2169 | * @sb: the empty superblock |
2082 | 2170 | * @data: unused |
... | ... | @@ -2125,6 +2213,8 @@ |
2125 | 2213 | [SMK_REVOKE_SUBJ] = { |
2126 | 2214 | "revoke-subject", &smk_revoke_subj_ops, |
2127 | 2215 | S_IRUGO|S_IWUSR}, |
2216 | + [SMK_CHANGE_RULE] = { | |
2217 | + "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, | |
2128 | 2218 | /* last one */ |
2129 | 2219 | {""} |
2130 | 2220 | }; |
security/tomoyo/tomoyo.c
... | ... | @@ -536,7 +536,7 @@ |
536 | 536 | }; |
537 | 537 | |
538 | 538 | /* Lock for GC. */ |
539 | -struct srcu_struct tomoyo_ss; | |
539 | +DEFINE_SRCU(tomoyo_ss); | |
540 | 540 | |
541 | 541 | /** |
542 | 542 | * tomoyo_init - Register TOMOYO Linux as a LSM module. |
... | ... | @@ -550,8 +550,7 @@ |
550 | 550 | if (!security_module_enable(&tomoyo_security_ops)) |
551 | 551 | return 0; |
552 | 552 | /* register ourselves with the security framework */ |
553 | - if (register_security(&tomoyo_security_ops) || | |
554 | - init_srcu_struct(&tomoyo_ss)) | |
553 | + if (register_security(&tomoyo_security_ops)) | |
555 | 554 | panic("Failure registering TOMOYO Linux"); |
556 | 555 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
557 | 556 | cred->security = &tomoyo_kernel_domain; |