diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 19:27:51 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 19:27:51 -0400 |
| commit | 2e1deaad1e48453cea782854ab87df3f78c121c2 (patch) | |
| tree | da0fe592dcc9ef6b0c4cd104a67af3c1d9e4c5d5 | |
| parent | 50528fabeb25f9883e2845f5147f5e00a1c57cf7 (diff) | |
| parent | b7ae9f064bec903bd4a9f257a35da4d1e9bbcc99 (diff) | |
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
| -rw-r--r-- | Documentation/devicetree/bindings/i2c/trivial-devices.txt | 2 | ||||
| -rw-r--r-- | Documentation/security/Smack.txt | 11 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.c | 31 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 3 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_i2c_infineon.c | 180 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_i2c_stm_st33.c | 64 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_ppi.c | 14 | ||||
| -rw-r--r-- | fs/nfs/super.c | 3 | ||||
| -rw-r--r-- | include/linux/security.h | 10 | ||||
| -rw-r--r-- | include/uapi/linux/magic.h | 1 | ||||
| -rw-r--r-- | kernel/seccomp.c | 2 | ||||
| -rw-r--r-- | security/capability.c | 3 | ||||
| -rw-r--r-- | security/integrity/ima/ima_main.c | 14 | ||||
| -rw-r--r-- | security/security.c | 4 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 39 | ||||
| -rw-r--r-- | security/smack/smack.h | 5 | ||||
| -rw-r--r-- | security/smack/smack_access.c | 2 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 4 | ||||
| -rw-r--r-- | security/smack/smackfs.c | 254 | ||||
| -rw-r--r-- | security/tomoyo/tomoyo.c | 5 |
20 files changed, 450 insertions, 201 deletions
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 446859fcdca4..ad6a73852f08 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt | |||
| @@ -35,6 +35,8 @@ fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 | |||
| 35 | fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer | 35 | fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer |
| 36 | fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller | 36 | fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller |
| 37 | fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec | 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 | maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator | 40 | maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator |
| 39 | maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs | 41 | maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs |
| 40 | maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface | 42 | maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface |
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt index 8a177e4b6e21..7a2d30c132e3 100644 --- a/Documentation/security/Smack.txt +++ b/Documentation/security/Smack.txt | |||
| @@ -117,6 +117,17 @@ access2 | |||
| 117 | ambient | 117 | ambient |
| 118 | This contains the Smack label applied to unlabeled network | 118 | This contains the Smack label applied to unlabeled network |
| 119 | packets. | 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 | cipso | 131 | cipso |
| 121 | This interface allows a specific CIPSO header to be assigned | 132 | This interface allows a specific CIPSO header to be assigned |
| 122 | to a Smack label. The format accepted on write is: | 133 | to a Smack label. The format accepted on write is: |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 0d2e82f95577..7c3b3dcbfbc8 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
| @@ -1337,7 +1337,7 @@ int tpm_pm_suspend(struct device *dev) | |||
| 1337 | { | 1337 | { |
| 1338 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1338 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 1339 | struct tpm_cmd_t cmd; | 1339 | struct tpm_cmd_t cmd; |
| 1340 | int rc; | 1340 | int rc, try; |
| 1341 | 1341 | ||
| 1342 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; | 1342 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; |
| 1343 | 1343 | ||
| @@ -1355,9 +1355,32 @@ int tpm_pm_suspend(struct device *dev) | |||
| 1355 | } | 1355 | } |
| 1356 | 1356 | ||
| 1357 | /* now do the actual savestate */ | 1357 | /* now do the actual savestate */ |
| 1358 | cmd.header.in = savestate_header; | 1358 | for (try = 0; try < TPM_RETRY; try++) { |
| 1359 | rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, | 1359 | cmd.header.in = savestate_header; |
| 1360 | "sending savestate before suspend"); | 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 | return rc; | 1384 | return rc; |
| 1362 | } | 1385 | } |
| 1363 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); | 1386 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 81b52015f669..0770d1d79366 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -32,10 +32,12 @@ enum tpm_const { | |||
| 32 | TPM_MINOR = 224, /* officially assigned */ | 32 | TPM_MINOR = 224, /* officially assigned */ |
| 33 | TPM_BUFSIZE = 4096, | 33 | TPM_BUFSIZE = 4096, |
| 34 | TPM_NUM_DEVICES = 256, | 34 | TPM_NUM_DEVICES = 256, |
| 35 | TPM_RETRY = 50, /* 5 seconds */ | ||
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 37 | enum tpm_timeout { | 38 | enum tpm_timeout { |
| 38 | TPM_TIMEOUT = 5, /* msecs */ | 39 | TPM_TIMEOUT = 5, /* msecs */ |
| 40 | TPM_TIMEOUT_RETRY = 100 /* msecs */ | ||
| 39 | }; | 41 | }; |
| 40 | 42 | ||
| 41 | /* TPM addresses */ | 43 | /* TPM addresses */ |
| @@ -44,6 +46,7 @@ enum tpm_addr { | |||
| 44 | TPM_ADDR = 0x4E, | 46 | TPM_ADDR = 0x4E, |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| 49 | #define TPM_WARN_RETRY 0x800 | ||
| 47 | #define TPM_WARN_DOING_SELFTEST 0x802 | 50 | #define TPM_WARN_DOING_SELFTEST 0x802 |
| 48 | #define TPM_ERR_DEACTIVATED 0x6 | 51 | #define TPM_ERR_DEACTIVATED 0x6 |
| 49 | #define TPM_ERR_DISABLED 0x7 | 52 | #define TPM_ERR_DISABLED 0x7 |
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 8fe7ac3d095b..37d5dcc10ea7 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2012 Infineon Technologies | 2 | * Copyright (C) 2012,2013 Infineon Technologies |
| 3 | * | 3 | * |
| 4 | * Authors: | 4 | * Authors: |
| 5 | * Peter Huewe <peter.huewe@infineon.com> | 5 | * Peter Huewe <peter.huewe@infineon.com> |
| @@ -56,13 +56,21 @@ | |||
| 56 | #define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) | 56 | #define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) |
| 57 | 57 | ||
| 58 | /* expected value for DIDVID register */ | 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 | ||
| 61 | |||
| 62 | enum i2c_chip_type { | ||
| 63 | SLB9635, | ||
| 64 | SLB9645, | ||
| 65 | UNKNOWN, | ||
| 66 | }; | ||
| 60 | 67 | ||
| 61 | /* Structure to store I2C TPM specific stuff */ | 68 | /* Structure to store I2C TPM specific stuff */ |
| 62 | struct tpm_inf_dev { | 69 | struct tpm_inf_dev { |
| 63 | struct i2c_client *client; | 70 | struct i2c_client *client; |
| 64 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ | 71 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ |
| 65 | struct tpm_chip *chip; | 72 | struct tpm_chip *chip; |
| 73 | enum i2c_chip_type chip_type; | ||
| 66 | }; | 74 | }; |
| 67 | 75 | ||
| 68 | static struct tpm_inf_dev tpm_dev; | 76 | static struct tpm_inf_dev tpm_dev; |
| @@ -90,10 +98,20 @@ static struct i2c_driver tpm_tis_i2c_driver; | |||
| 90 | static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) | 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 }; | 101 | struct i2c_msg msg1 = { |
| 94 | struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer }; | 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 | int count; | 115 | int count; |
| 98 | 116 | ||
| 99 | /* Lock the adapter for the duration of the whole sequence. */ | 117 | /* Lock the adapter for the duration of the whole sequence. */ |
| @@ -101,30 +119,53 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) | |||
| 101 | return -EOPNOTSUPP; | 119 | return -EOPNOTSUPP; |
| 102 | i2c_lock_adapter(tpm_dev.client->adapter); | 120 | i2c_lock_adapter(tpm_dev.client->adapter); |
| 103 | 121 | ||
| 104 | for (count = 0; count < MAX_COUNT; count++) { | 122 | if (tpm_dev.chip_type == SLB9645) { |
| 105 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | 123 | /* use a combined read for newer chips |
| 106 | if (rc > 0) | 124 | * unfortunately the smbus functions are not suitable due to |
| 107 | break; /* break here to skip sleep */ | 125 | * the 32 byte limit of the smbus. |
| 108 | 126 | * retries should usually not be needed, but are kept just to | |
| 109 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | 127 | * be on the safe side. |
| 110 | } | 128 | */ |
| 111 | 129 | for (count = 0; count < MAX_COUNT; count++) { | |
| 112 | if (rc <= 0) | 130 | rc = __i2c_transfer(tpm_dev.client->adapter, msgs, 2); |
| 113 | goto out; | 131 | if (rc > 0) |
| 114 | 132 | break; /* break here to skip sleep */ | |
| 115 | /* After the TPM has successfully received the register address it needs | 133 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); |
| 116 | * some time, thus we're sleeping here again, before retrieving the data | 134 | } |
| 117 | */ | 135 | } else { |
| 118 | for (count = 0; count < MAX_COUNT; count++) { | 136 | /* slb9635 protocol should work in all cases */ |
| 119 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | 137 | for (count = 0; count < MAX_COUNT; count++) { |
| 120 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); | 138 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); |
| 121 | if (rc > 0) | 139 | if (rc > 0) |
| 122 | break; | 140 | break; /* break here to skip sleep */ |
| 141 | |||
| 142 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | ||
| 143 | } | ||
| 123 | 144 | ||
| 145 | if (rc <= 0) | ||
| 146 | goto out; | ||
| 147 | |||
| 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 | out: | 160 | out: |
| 127 | i2c_unlock_adapter(tpm_dev.client->adapter); | 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 | if (rc <= 0) | 169 | if (rc <= 0) |
| 129 | return -EIO; | 170 | return -EIO; |
| 130 | 171 | ||
| @@ -138,7 +179,11 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, | |||
| 138 | int rc = -EIO; | 179 | int rc = -EIO; |
| 139 | int count; | 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 | if (len > TPM_BUFSIZE) | 188 | if (len > TPM_BUFSIZE) |
| 144 | return -EINVAL; | 189 | return -EINVAL; |
| @@ -154,16 +199,24 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, | |||
| 154 | /* | 199 | /* |
| 155 | * NOTE: We have to use these special mechanisms here and unfortunately | 200 | * NOTE: We have to use these special mechanisms here and unfortunately |
| 156 | * cannot rely on the standard behavior of i2c_transfer. | 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 | for (count = 0; count < max_count; count++) { | 205 | for (count = 0; count < max_count; count++) { |
| 159 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | 206 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); |
| 160 | if (rc > 0) | 207 | if (rc > 0) |
| 161 | break; | 208 | break; |
| 162 | |||
| 163 | usleep_range(sleep_low, sleep_hi); | 209 | usleep_range(sleep_low, sleep_hi); |
| 164 | } | 210 | } |
| 165 | 211 | ||
| 166 | i2c_unlock_adapter(tpm_dev.client->adapter); | 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 | if (rc <= 0) | 220 | if (rc <= 0) |
| 168 | return -EIO; | 221 | return -EIO; |
| 169 | 222 | ||
| @@ -283,11 +336,18 @@ static int request_locality(struct tpm_chip *chip, int loc) | |||
| 283 | static u8 tpm_tis_i2c_status(struct tpm_chip *chip) | 336 | static u8 tpm_tis_i2c_status(struct tpm_chip *chip) |
| 284 | { | 337 | { |
| 285 | /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ | 338 | /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ |
| 286 | u8 buf; | 339 | u8 buf = 0xFF; |
| 287 | if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) | 340 | u8 i = 0; |
| 288 | return 0; | 341 | |
| 289 | else | 342 | do { |
| 290 | return buf; | 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 | static void tpm_tis_i2c_ready(struct tpm_chip *chip) | 353 | static void tpm_tis_i2c_ready(struct tpm_chip *chip) |
| @@ -328,7 +388,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | |||
| 328 | 388 | ||
| 329 | /* check current status */ | 389 | /* check current status */ |
| 330 | *status = tpm_tis_i2c_status(chip); | 390 | *status = tpm_tis_i2c_status(chip); |
| 331 | if ((*status & mask) == mask) | 391 | if ((*status != 0xFF) && (*status & mask) == mask) |
| 332 | return 0; | 392 | return 0; |
| 333 | 393 | ||
| 334 | stop = jiffies + timeout; | 394 | stop = jiffies + timeout; |
| @@ -372,7 +432,6 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 372 | /* avoid endless loop in case of broken HW */ | 432 | /* avoid endless loop in case of broken HW */ |
| 373 | if (retries > MAX_COUNT_LONG) | 433 | if (retries > MAX_COUNT_LONG) |
| 374 | return -EIO; | 434 | return -EIO; |
| 375 | |||
| 376 | } | 435 | } |
| 377 | return size; | 436 | return size; |
| 378 | } | 437 | } |
| @@ -480,7 +539,6 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 480 | rc = -EIO; | 539 | rc = -EIO; |
| 481 | goto out_err; | 540 | goto out_err; |
| 482 | } | 541 | } |
| 483 | |||
| 484 | } | 542 | } |
| 485 | 543 | ||
| 486 | /* write last byte */ | 544 | /* write last byte */ |
| @@ -568,6 +626,7 @@ static int tpm_tis_i2c_init(struct device *dev) | |||
| 568 | 626 | ||
| 569 | chip = tpm_register_hardware(dev, &tpm_tis_i2c); | 627 | chip = tpm_register_hardware(dev, &tpm_tis_i2c); |
| 570 | if (!chip) { | 628 | if (!chip) { |
| 629 | dev_err(dev, "could not register hardware\n"); | ||
| 571 | rc = -ENODEV; | 630 | rc = -ENODEV; |
| 572 | goto out_err; | 631 | goto out_err; |
| 573 | } | 632 | } |
| @@ -582,20 +641,24 @@ static int tpm_tis_i2c_init(struct device *dev) | |||
| 582 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 641 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
| 583 | 642 | ||
| 584 | if (request_locality(chip, 0) != 0) { | 643 | if (request_locality(chip, 0) != 0) { |
| 644 | dev_err(dev, "could not request locality\n"); | ||
| 585 | rc = -ENODEV; | 645 | rc = -ENODEV; |
| 586 | goto out_vendor; | 646 | goto out_vendor; |
| 587 | } | 647 | } |
| 588 | 648 | ||
| 589 | /* read four bytes from DID_VID register */ | 649 | /* read four bytes from DID_VID register */ |
| 590 | if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { | 650 | if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { |
| 651 | dev_err(dev, "could not read vendor id\n"); | ||
| 591 | rc = -EIO; | 652 | rc = -EIO; |
| 592 | goto out_release; | 653 | goto out_release; |
| 593 | } | 654 | } |
| 594 | 655 | ||
| 595 | /* create DID_VID register value, after swapping to little-endian */ | 656 | if (vendor == TPM_TIS_I2C_DID_VID_9645) { |
| 596 | vendor = be32_to_cpu((__be32) vendor); | 657 | tpm_dev.chip_type = SLB9645; |
| 597 | 658 | } else if (vendor == TPM_TIS_I2C_DID_VID_9635) { | |
| 598 | if (vendor != TPM_TIS_I2C_DID_VID) { | 659 | tpm_dev.chip_type = SLB9635; |
| 660 | } else { | ||
| 661 | dev_err(dev, "vendor id did not match! ID was %08x\n", vendor); | ||
| 599 | rc = -ENODEV; | 662 | rc = -ENODEV; |
| 600 | goto out_release; | 663 | goto out_release; |
| 601 | } | 664 | } |
| @@ -631,22 +694,53 @@ out_err: | |||
| 631 | 694 | ||
| 632 | static const struct i2c_device_id tpm_tis_i2c_table[] = { | 695 | static const struct i2c_device_id tpm_tis_i2c_table[] = { |
| 633 | {"tpm_i2c_infineon", 0}, | 696 | {"tpm_i2c_infineon", 0}, |
| 697 | {"slb9635tt", 0}, | ||
| 698 | {"slb9645tt", 1}, | ||
| 634 | {}, | 699 | {}, |
| 635 | }; | 700 | }; |
| 636 | 701 | ||
| 637 | MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); | 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 | static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); | 729 | static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); |
| 639 | 730 | ||
| 640 | static int tpm_tis_i2c_probe(struct i2c_client *client, | 731 | static int tpm_tis_i2c_probe(struct i2c_client *client, |
| 641 | const struct i2c_device_id *id) | 732 | const struct i2c_device_id *id) |
| 642 | { | 733 | { |
| 643 | int rc; | 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 | return -EBUSY; /* We only support one client */ | 739 | return -EBUSY; /* We only support one client */ |
| 740 | } | ||
| 646 | 741 | ||
| 647 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 742 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| 648 | dev_err(&client->dev, | 743 | dev_err(dev, "no algorithms associated to the i2c bus\n"); |
| 649 | "no algorithms associated to the i2c bus\n"); | ||
| 650 | return -ENODEV; | 744 | return -ENODEV; |
| 651 | } | 745 | } |
| 652 | 746 | ||
| @@ -682,7 +776,6 @@ static int tpm_tis_i2c_remove(struct i2c_client *client) | |||
| 682 | } | 776 | } |
| 683 | 777 | ||
| 684 | static struct i2c_driver tpm_tis_i2c_driver = { | 778 | static struct i2c_driver tpm_tis_i2c_driver = { |
| 685 | |||
| 686 | .id_table = tpm_tis_i2c_table, | 779 | .id_table = tpm_tis_i2c_table, |
| 687 | .probe = tpm_tis_i2c_probe, | 780 | .probe = tpm_tis_i2c_probe, |
| 688 | .remove = tpm_tis_i2c_remove, | 781 | .remove = tpm_tis_i2c_remove, |
| @@ -690,11 +783,12 @@ static struct i2c_driver tpm_tis_i2c_driver = { | |||
| 690 | .name = "tpm_i2c_infineon", | 783 | .name = "tpm_i2c_infineon", |
| 691 | .owner = THIS_MODULE, | 784 | .owner = THIS_MODULE, |
| 692 | .pm = &tpm_tis_i2c_ops, | 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 | module_i2c_driver(tpm_tis_i2c_driver); | 790 | module_i2c_driver(tpm_tis_i2c_driver); |
| 697 | MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); | 791 | MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); |
| 698 | MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); | 792 | MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); |
| 699 | MODULE_VERSION("2.1.5"); | 793 | MODULE_VERSION("2.2.0"); |
| 700 | MODULE_LICENSE("GPL"); | 794 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c index 1f5f71e14abe..5bb8e2ddd3b3 100644 --- a/drivers/char/tpm/tpm_i2c_stm_st33.c +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/i2c.h> | 36 | #include <linux/i2c.h> |
| 37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
| 38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
| 39 | #include <linux/module.h> | ||
| 40 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
| 41 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
| 42 | #include <linux/init.h> | 41 | #include <linux/init.h> |
| @@ -50,7 +49,6 @@ | |||
| 50 | #include <linux/uaccess.h> | 49 | #include <linux/uaccess.h> |
| 51 | #include <linux/io.h> | 50 | #include <linux/io.h> |
| 52 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
| 53 | #include <linux/sched.h> | ||
| 54 | 52 | ||
| 55 | #include "tpm.h" | 53 | #include "tpm.h" |
| 56 | #include "tpm_i2c_stm_st33.h" | 54 | #include "tpm_i2c_stm_st33.h" |
| @@ -178,7 +176,7 @@ static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip, | |||
| 178 | struct i2c_client *client; | 176 | struct i2c_client *client; |
| 179 | struct st33zp24_platform_data *pin_infos; | 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 | pin_infos = client->dev.platform_data; | 180 | pin_infos = client->dev.platform_data; |
| 183 | 181 | ||
| 184 | status = wait_for_completion_interruptible_timeout( | 182 | status = wait_for_completion_interruptible_timeout( |
| @@ -197,12 +195,12 @@ static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition, | |||
| 197 | int status = 2; | 195 | int status = 2; |
| 198 | struct i2c_client *client; | 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 | status = _wait_for_interrupt_serirq_timeout(chip, timeout); | 200 | status = _wait_for_interrupt_serirq_timeout(chip, timeout); |
| 203 | if (!status) { | 201 | if (!status) { |
| 204 | status = -EBUSY; | 202 | status = -EBUSY; |
| 205 | } else{ | 203 | } else { |
| 206 | clear_interruption(client); | 204 | clear_interruption(client); |
| 207 | if (condition) | 205 | if (condition) |
| 208 | status = 1; | 206 | status = 1; |
| @@ -219,7 +217,7 @@ static void tpm_stm_i2c_cancel(struct tpm_chip *chip) | |||
| 219 | struct i2c_client *client; | 217 | struct i2c_client *client; |
| 220 | u8 data; | 218 | u8 data; |
| 221 | 219 | ||
| 222 | client = (struct i2c_client *) TPM_VPRIV(chip); | 220 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 223 | 221 | ||
| 224 | data = TPM_STS_COMMAND_READY; | 222 | data = TPM_STS_COMMAND_READY; |
| 225 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); | 223 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); |
| @@ -236,7 +234,7 @@ static u8 tpm_stm_i2c_status(struct tpm_chip *chip) | |||
| 236 | { | 234 | { |
| 237 | struct i2c_client *client; | 235 | struct i2c_client *client; |
| 238 | u8 data; | 236 | u8 data; |
| 239 | client = (struct i2c_client *) TPM_VPRIV(chip); | 237 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 240 | 238 | ||
| 241 | I2C_READ_DATA(client, TPM_STS, &data, 1); | 239 | I2C_READ_DATA(client, TPM_STS, &data, 1); |
| 242 | return data; | 240 | return data; |
| @@ -254,7 +252,7 @@ static int check_locality(struct tpm_chip *chip) | |||
| 254 | u8 data; | 252 | u8 data; |
| 255 | u8 status; | 253 | u8 status; |
| 256 | 254 | ||
| 257 | client = (struct i2c_client *) TPM_VPRIV(chip); | 255 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 258 | 256 | ||
| 259 | status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); | 257 | status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); |
| 260 | if (status && (data & | 258 | if (status && (data & |
| @@ -278,7 +276,7 @@ static int request_locality(struct tpm_chip *chip) | |||
| 278 | struct i2c_client *client; | 276 | struct i2c_client *client; |
| 279 | u8 data; | 277 | u8 data; |
| 280 | 278 | ||
| 281 | client = (struct i2c_client *) TPM_VPRIV(chip); | 279 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 282 | 280 | ||
| 283 | if (check_locality(chip) == chip->vendor.locality) | 281 | if (check_locality(chip) == chip->vendor.locality) |
| 284 | return chip->vendor.locality; | 282 | return chip->vendor.locality; |
| @@ -294,7 +292,7 @@ static int request_locality(struct tpm_chip *chip) | |||
| 294 | chip->vendor.timeout_a); | 292 | chip->vendor.timeout_a); |
| 295 | if (rc > 0) | 293 | if (rc > 0) |
| 296 | return chip->vendor.locality; | 294 | return chip->vendor.locality; |
| 297 | } else{ | 295 | } else { |
| 298 | stop = jiffies + chip->vendor.timeout_a; | 296 | stop = jiffies + chip->vendor.timeout_a; |
| 299 | do { | 297 | do { |
| 300 | if (check_locality(chip) >= 0) | 298 | if (check_locality(chip) >= 0) |
| @@ -316,7 +314,7 @@ static void release_locality(struct tpm_chip *chip) | |||
| 316 | struct i2c_client *client; | 314 | struct i2c_client *client; |
| 317 | u8 data; | 315 | u8 data; |
| 318 | 316 | ||
| 319 | client = (struct i2c_client *) TPM_VPRIV(chip); | 317 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 320 | data = TPM_ACCESS_ACTIVE_LOCALITY; | 318 | data = TPM_ACCESS_ACTIVE_LOCALITY; |
| 321 | 319 | ||
| 322 | I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); | 320 | I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); |
| @@ -333,7 +331,7 @@ static int get_burstcount(struct tpm_chip *chip) | |||
| 333 | int burstcnt, status; | 331 | int burstcnt, status; |
| 334 | u8 tpm_reg, temp; | 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 | stop = jiffies + chip->vendor.timeout_d; | 336 | stop = jiffies + chip->vendor.timeout_d; |
| 339 | do { | 337 | do { |
| @@ -379,7 +377,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | |||
| 379 | mask), timeout); | 377 | mask), timeout); |
| 380 | if (rc > 0) | 378 | if (rc > 0) |
| 381 | return 0; | 379 | return 0; |
| 382 | } else{ | 380 | } else { |
| 383 | stop = jiffies + timeout; | 381 | stop = jiffies + timeout; |
| 384 | do { | 382 | do { |
| 385 | msleep(TPM_TIMEOUT); | 383 | msleep(TPM_TIMEOUT); |
| @@ -403,7 +401,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 403 | int size = 0, burstcnt, len; | 401 | int size = 0, burstcnt, len; |
| 404 | struct i2c_client *client; | 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 | while (size < count && | 406 | while (size < count && |
| 409 | wait_for_stat(chip, | 407 | wait_for_stat(chip, |
| @@ -433,7 +431,7 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) | |||
| 433 | 431 | ||
| 434 | disable_irq_nosync(irq); | 432 | disable_irq_nosync(irq); |
| 435 | 433 | ||
| 436 | client = (struct i2c_client *) TPM_VPRIV(chip); | 434 | client = (struct i2c_client *)TPM_VPRIV(chip); |
| 437 | pin_infos = client->dev.platform_data; | 435 | pin_infos = client->dev.platform_data; |
| 438 | 436 | ||
| 439 | complete(&pin_infos->irq_detection); | 437 | complete(&pin_infos->irq_detection); |
| @@ -453,8 +451,7 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) | |||
| 453 | static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | 451 | static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, |
| 454 | size_t len) | 452 | size_t len) |
| 455 | { | 453 | { |
| 456 | u32 status, | 454 | u32 status, burstcnt = 0, i, size; |
| 457 | burstcnt = 0, i, size; | ||
| 458 | int ret; | 455 | int ret; |
| 459 | u8 data; | 456 | u8 data; |
| 460 | struct i2c_client *client; | 457 | struct i2c_client *client; |
| @@ -483,7 +480,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | |||
| 483 | } | 480 | } |
| 484 | } | 481 | } |
| 485 | 482 | ||
| 486 | for (i = 0 ; i < len - 1 ;) { | 483 | for (i = 0; i < len - 1;) { |
| 487 | burstcnt = get_burstcount(chip); | 484 | burstcnt = get_burstcount(chip); |
| 488 | size = min_t(int, len - i - 1, burstcnt); | 485 | size = min_t(int, len - i - 1, burstcnt); |
| 489 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); | 486 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); |
| @@ -547,7 +544,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | |||
| 547 | goto out; | 544 | goto out; |
| 548 | } | 545 | } |
| 549 | 546 | ||
| 550 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | 547 | expected = be32_to_cpu(*(__be32 *)(buf + 2)); |
| 551 | if (expected > count) { | 548 | if (expected > count) { |
| 552 | size = -EIO; | 549 | size = -EIO; |
| 553 | goto out; | 550 | goto out; |
| @@ -569,7 +566,7 @@ out: | |||
| 569 | 566 | ||
| 570 | static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status) | 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 | static const struct file_operations tpm_st33_i2c_fops = { | 572 | static const struct file_operations tpm_st33_i2c_fops = { |
| @@ -617,7 +614,7 @@ static struct tpm_vendor_specific st_i2c_tpm = { | |||
| 617 | .miscdev = {.fops = &tpm_st33_i2c_fops,}, | 614 | .miscdev = {.fops = &tpm_st33_i2c_fops,}, |
| 618 | }; | 615 | }; |
| 619 | 616 | ||
| 620 | static int interrupts ; | 617 | static int interrupts; |
| 621 | module_param(interrupts, int, 0444); | 618 | module_param(interrupts, int, 0444); |
| 622 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 619 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
| 623 | 620 | ||
| @@ -714,7 +711,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 714 | "TPM SERIRQ management", chip); | 711 | "TPM SERIRQ management", chip); |
| 715 | if (err < 0) { | 712 | if (err < 0) { |
| 716 | dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", | 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 | goto _irq_set; | 715 | goto _irq_set; |
| 719 | } | 716 | } |
| 720 | 717 | ||
| @@ -754,7 +751,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 754 | dev_info(chip->dev, "TPM I2C Initialized\n"); | 751 | dev_info(chip->dev, "TPM I2C Initialized\n"); |
| 755 | return 0; | 752 | return 0; |
| 756 | _irq_set: | 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 | _gpio_init2: | 755 | _gpio_init2: |
| 759 | if (interrupts) | 756 | if (interrupts) |
| 760 | gpio_free(platform_data->io_serirq); | 757 | gpio_free(platform_data->io_serirq); |
| @@ -784,7 +781,7 @@ static int tpm_st33_i2c_remove(struct i2c_client *client) | |||
| 784 | { | 781 | { |
| 785 | struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); | 782 | struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); |
| 786 | struct st33zp24_platform_data *pin_infos = | 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 | if (pin_infos != NULL) { | 786 | if (pin_infos != NULL) { |
| 790 | free_irq(pin_infos->io_serirq, chip); | 787 | free_irq(pin_infos->io_serirq, chip); |
| @@ -823,9 +820,9 @@ static int tpm_st33_i2c_pm_suspend(struct device *dev) | |||
| 823 | struct st33zp24_platform_data *pin_infos = dev->platform_data; | 820 | struct st33zp24_platform_data *pin_infos = dev->platform_data; |
| 824 | int ret = 0; | 821 | int ret = 0; |
| 825 | 822 | ||
| 826 | if (power_mgt) | 823 | if (power_mgt) { |
| 827 | gpio_set_value(pin_infos->io_lpcpd, 0); | 824 | gpio_set_value(pin_infos->io_lpcpd, 0); |
| 828 | else{ | 825 | } else { |
| 829 | if (chip->data_buffer == NULL) | 826 | if (chip->data_buffer == NULL) |
| 830 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | 827 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; |
| 831 | ret = tpm_pm_suspend(dev); | 828 | ret = tpm_pm_suspend(dev); |
| @@ -851,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct device *dev) | |||
| 851 | (chip->vendor.status(chip) & | 848 | (chip->vendor.status(chip) & |
| 852 | TPM_STS_VALID) == TPM_STS_VALID, | 849 | TPM_STS_VALID) == TPM_STS_VALID, |
| 853 | chip->vendor.timeout_b); | 850 | chip->vendor.timeout_b); |
| 854 | } else{ | 851 | } else { |
| 855 | if (chip->data_buffer == NULL) | 852 | if (chip->data_buffer == NULL) |
| 856 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | 853 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; |
| 857 | ret = tpm_pm_resume(dev); | 854 | ret = tpm_pm_resume(dev); |
| 858 | if (!ret) | 855 | if (!ret) |
| 859 | tpm_do_selftest(chip); | 856 | tpm_do_selftest(chip); |
| 860 | } | 857 | } |
| 861 | return ret; | 858 | return ret; |
| 862 | } /* tpm_st33_i2c_pm_resume() */ | 859 | } /* tpm_st33_i2c_pm_resume() */ |
| @@ -867,7 +864,8 @@ static const struct i2c_device_id tpm_st33_i2c_id[] = { | |||
| 867 | {} | 864 | {} |
| 868 | }; | 865 | }; |
| 869 | MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id); | 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 | static struct i2c_driver tpm_st33_i2c_driver = { | 869 | static struct i2c_driver tpm_st33_i2c_driver = { |
| 872 | .driver = { | 870 | .driver = { |
| 873 | .owner = THIS_MODULE, | 871 | .owner = THIS_MODULE, |
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 720ebcf29fdf..2168d15bc728 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c | |||
| @@ -158,9 +158,9 @@ static ssize_t tpm_store_ppi_request(struct device *dev, | |||
| 158 | ACPI_TYPE_STRING); | 158 | ACPI_TYPE_STRING); |
| 159 | if (ACPI_FAILURE(status)) | 159 | if (ACPI_FAILURE(status)) |
| 160 | return -ENOMEM; | 160 | return -ENOMEM; |
| 161 | strncpy(version, | 161 | strlcpy(version, |
| 162 | ((union acpi_object *)output.pointer)->string.pointer, | 162 | ((union acpi_object *)output.pointer)->string.pointer, |
| 163 | PPI_VERSION_LEN); | 163 | PPI_VERSION_LEN + 1); |
| 164 | kfree(output.pointer); | 164 | kfree(output.pointer); |
| 165 | output.length = ACPI_ALLOCATE_BUFFER; | 165 | output.length = ACPI_ALLOCATE_BUFFER; |
| 166 | output.pointer = NULL; | 166 | output.pointer = NULL; |
| @@ -237,9 +237,9 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, | |||
| 237 | ACPI_TYPE_STRING); | 237 | ACPI_TYPE_STRING); |
| 238 | if (ACPI_FAILURE(status)) | 238 | if (ACPI_FAILURE(status)) |
| 239 | return -ENOMEM; | 239 | return -ENOMEM; |
| 240 | strncpy(version, | 240 | strlcpy(version, |
| 241 | ((union acpi_object *)output.pointer)->string.pointer, | 241 | ((union acpi_object *)output.pointer)->string.pointer, |
| 242 | PPI_VERSION_LEN); | 242 | PPI_VERSION_LEN + 1); |
| 243 | /* | 243 | /* |
| 244 | * PPI spec defines params[3].type as empty package, but some platforms | 244 | * PPI spec defines params[3].type as empty package, but some platforms |
| 245 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for | 245 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for |
| @@ -351,7 +351,7 @@ cleanup: | |||
| 351 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) | 351 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) |
| 352 | { | 352 | { |
| 353 | char *str = buf; | 353 | char *str = buf; |
| 354 | char version[PPI_VERSION_LEN]; | 354 | char version[PPI_VERSION_LEN + 1]; |
| 355 | acpi_handle handle; | 355 | acpi_handle handle; |
| 356 | acpi_status status; | 356 | acpi_status status; |
| 357 | struct acpi_object_list input; | 357 | struct acpi_object_list input; |
| @@ -381,9 +381,9 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) | |||
| 381 | if (ACPI_FAILURE(status)) | 381 | if (ACPI_FAILURE(status)) |
| 382 | return -ENOMEM; | 382 | return -ENOMEM; |
| 383 | 383 | ||
| 384 | strncpy(version, | 384 | strlcpy(version, |
| 385 | ((union acpi_object *)output.pointer)->string.pointer, | 385 | ((union acpi_object *)output.pointer)->string.pointer, |
| 386 | PPI_VERSION_LEN); | 386 | PPI_VERSION_LEN + 1); |
| 387 | kfree(output.pointer); | 387 | kfree(output.pointer); |
| 388 | output.length = ACPI_ALLOCATE_BUFFER; | 388 | output.length = ACPI_ALLOCATE_BUFFER; |
| 389 | output.pointer = NULL; | 389 | output.pointer = NULL; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index eb494f6a4c6b..1bb071dca9ab 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -2385,10 +2385,9 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | |||
| 2385 | struct nfs_mount_info *mount_info) | 2385 | struct nfs_mount_info *mount_info) |
| 2386 | { | 2386 | { |
| 2387 | /* clone any lsm security options from the parent to the new sb */ | 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 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) | 2388 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) |
| 2390 | return -ESTALE; | 2389 | return -ESTALE; |
| 2391 | return 0; | 2390 | return security_sb_clone_mnt_opts(mount_info->cloned->sb, s); |
| 2392 | } | 2391 | } |
| 2393 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); | 2392 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); |
| 2394 | 2393 | ||
diff --git a/include/linux/security.h b/include/linux/security.h index 032c366ef1c6..4686491852a7 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -1440,7 +1440,7 @@ struct security_operations { | |||
| 1440 | struct path *new_path); | 1440 | struct path *new_path); |
| 1441 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1441 | int (*sb_set_mnt_opts) (struct super_block *sb, |
| 1442 | struct security_mnt_opts *opts); | 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 | struct super_block *newsb); | 1444 | struct super_block *newsb); |
| 1445 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1445 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
| 1446 | 1446 | ||
| @@ -1726,7 +1726,7 @@ int security_sb_mount(const char *dev_name, struct path *path, | |||
| 1726 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1726 | int security_sb_umount(struct vfsmount *mnt, int flags); |
| 1727 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1727 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
| 1728 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 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 | struct super_block *newsb); | 1730 | struct super_block *newsb); |
| 1731 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 1731 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
| 1732 | 1732 | ||
| @@ -2016,9 +2016,11 @@ static inline int security_sb_set_mnt_opts(struct super_block *sb, | |||
| 2016 | return 0; | 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 | struct super_block *newsb) | 2020 | struct super_block *newsb) |
| 2021 | { } | 2021 | { |
| 2022 | return 0; | ||
| 2023 | } | ||
| 2022 | 2024 | ||
| 2023 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 2025 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
| 2024 | { | 2026 | { |
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 873e086ce3a1..249df3720be2 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #define DEBUGFS_MAGIC 0x64626720 | 11 | #define DEBUGFS_MAGIC 0x64626720 |
| 12 | #define SECURITYFS_MAGIC 0x73636673 | 12 | #define SECURITYFS_MAGIC 0x73636673 |
| 13 | #define SELINUX_MAGIC 0xf97cff8c | 13 | #define SELINUX_MAGIC 0xf97cff8c |
| 14 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ | ||
| 14 | #define RAMFS_MAGIC 0x858458f6 /* some random number */ | 15 | #define RAMFS_MAGIC 0x858458f6 /* some random number */ |
| 15 | #define TMPFS_MAGIC 0x01021994 | 16 | #define TMPFS_MAGIC 0x01021994 |
| 16 | #define HUGETLBFS_MAGIC 0x958458f6 /* some random number */ | 17 | #define HUGETLBFS_MAGIC 0x958458f6 /* some random number */ |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 5af44b593770..b7a10048a32c 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
| @@ -160,6 +160,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) | |||
| 160 | case BPF_S_ALU_AND_X: | 160 | case BPF_S_ALU_AND_X: |
| 161 | case BPF_S_ALU_OR_K: | 161 | case BPF_S_ALU_OR_K: |
| 162 | case BPF_S_ALU_OR_X: | 162 | case BPF_S_ALU_OR_X: |
| 163 | case BPF_S_ALU_XOR_K: | ||
| 164 | case BPF_S_ALU_XOR_X: | ||
| 163 | case BPF_S_ALU_LSH_K: | 165 | case BPF_S_ALU_LSH_K: |
| 164 | case BPF_S_ALU_LSH_X: | 166 | case BPF_S_ALU_LSH_X: |
| 165 | case BPF_S_ALU_RSH_K: | 167 | case BPF_S_ALU_RSH_K: |
diff --git a/security/capability.c b/security/capability.c index 6783c3e6c88e..1728d4e375db 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -98,9 +98,10 @@ static int cap_sb_set_mnt_opts(struct super_block *sb, | |||
| 98 | return 0; | 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 | struct super_block *newsb) | 102 | struct super_block *newsb) |
| 103 | { | 103 | { |
| 104 | return 0; | ||
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 107 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 3b3b7e6bf8da..6c491a63128e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -189,11 +189,9 @@ static int process_measurement(struct file *file, const char *filename, | |||
| 189 | if (rc != 0) | 189 | if (rc != 0) |
| 190 | goto out_digsig; | 190 | goto out_digsig; |
| 191 | 191 | ||
| 192 | if (function != BPRM_CHECK) | 192 | pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename; |
| 193 | pathname = ima_d_path(&file->f_path, &pathbuf); | ||
| 194 | |||
| 195 | if (!pathname) | 193 | if (!pathname) |
| 196 | pathname = filename; | 194 | pathname = (const char *)file->f_dentry->d_name.name; |
| 197 | 195 | ||
| 198 | if (action & IMA_MEASURE) | 196 | if (action & IMA_MEASURE) |
| 199 | ima_store_measurement(iint, file, pathname); | 197 | ima_store_measurement(iint, file, pathname); |
| @@ -226,8 +224,7 @@ out: | |||
| 226 | int ima_file_mmap(struct file *file, unsigned long prot) | 224 | int ima_file_mmap(struct file *file, unsigned long prot) |
| 227 | { | 225 | { |
| 228 | if (file && (prot & PROT_EXEC)) | 226 | if (file && (prot & PROT_EXEC)) |
| 229 | return process_measurement(file, file->f_dentry->d_name.name, | 227 | return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK); |
| 230 | MAY_EXEC, MMAP_CHECK); | ||
| 231 | return 0; | 228 | return 0; |
| 232 | } | 229 | } |
| 233 | 230 | ||
| @@ -265,7 +262,7 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
| 265 | int ima_file_check(struct file *file, int mask) | 262 | int ima_file_check(struct file *file, int mask) |
| 266 | { | 263 | { |
| 267 | ima_rdwr_violation_check(file); | 264 | ima_rdwr_violation_check(file); |
| 268 | return process_measurement(file, file->f_dentry->d_name.name, | 265 | return process_measurement(file, NULL, |
| 269 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 266 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
| 270 | FILE_CHECK); | 267 | FILE_CHECK); |
| 271 | } | 268 | } |
| @@ -290,8 +287,7 @@ int ima_module_check(struct file *file) | |||
| 290 | #endif | 287 | #endif |
| 291 | return 0; /* We rely on module signature checking */ | 288 | return 0; /* We rely on module signature checking */ |
| 292 | } | 289 | } |
| 293 | return process_measurement(file, file->f_dentry->d_name.name, | 290 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); |
| 294 | MAY_EXEC, MODULE_CHECK); | ||
| 295 | } | 291 | } |
| 296 | 292 | ||
| 297 | static int __init init_ima(void) | 293 | static int __init init_ima(void) |
diff --git a/security/security.c b/security/security.c index 03f248b84e9f..a3dce87d1aef 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -299,10 +299,10 @@ int security_sb_set_mnt_opts(struct super_block *sb, | |||
| 299 | } | 299 | } |
| 300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 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 | struct super_block *newsb) | 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 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); | 307 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
| 308 | 308 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7171a957b933..feb2f42c5a07 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -751,7 +751,37 @@ out_double_mount: | |||
| 751 | goto out; | 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 | struct super_block *newsb) | 785 | struct super_block *newsb) |
| 756 | { | 786 | { |
| 757 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; | 787 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; |
| @@ -766,14 +796,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 766 | * mount options. thus we can safely deal with this superblock later | 796 | * mount options. thus we can safely deal with this superblock later |
| 767 | */ | 797 | */ |
| 768 | if (!ss_initialized) | 798 | if (!ss_initialized) |
| 769 | return; | 799 | return 0; |
| 770 | 800 | ||
| 771 | /* how can we clone if the old one wasn't set up?? */ | 801 | /* how can we clone if the old one wasn't set up?? */ |
| 772 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 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 | if (newsbsec->flags & SE_SBINITIALIZED) | 805 | if (newsbsec->flags & SE_SBINITIALIZED) |
| 776 | return; | 806 | return selinux_cmp_sb_context(oldsb, newsb); |
| 777 | 807 | ||
| 778 | mutex_lock(&newsbsec->lock); | 808 | mutex_lock(&newsbsec->lock); |
| 779 | 809 | ||
| @@ -806,6 +836,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 806 | 836 | ||
| 807 | sb_finish_set_opts(newsb); | 837 | sb_finish_set_opts(newsb); |
| 808 | mutex_unlock(&newsbsec->lock); | 838 | mutex_unlock(&newsbsec->lock); |
| 839 | return 0; | ||
| 809 | } | 840 | } |
| 810 | 841 | ||
| 811 | static int selinux_parse_opts_str(char *options, | 842 | static int selinux_parse_opts_str(char *options, |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 99b36124f712..8ad30955e15d 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -149,11 +149,6 @@ struct smack_known { | |||
| 149 | #define SMACK_CIPSO_SOCKET 1 | 149 | #define SMACK_CIPSO_SOCKET 1 |
| 150 | 150 | ||
| 151 | /* | 151 | /* |
| 152 | * smackfs magic number | ||
| 153 | */ | ||
| 154 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ | ||
| 155 | |||
| 156 | /* | ||
| 157 | * CIPSO defaults. | 152 | * CIPSO defaults. |
| 158 | */ | 153 | */ |
| 159 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ | 154 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index db14689a21e0..2e397a88d410 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
| @@ -252,6 +252,8 @@ static inline void smack_str_from_perm(char *string, int access) | |||
| 252 | string[i++] = 'x'; | 252 | string[i++] = 'x'; |
| 253 | if (access & MAY_APPEND) | 253 | if (access & MAY_APPEND) |
| 254 | string[i++] = 'a'; | 254 | string[i++] = 'a'; |
| 255 | if (access & MAY_TRANSMUTE) | ||
| 256 | string[i++] = 't'; | ||
| 255 | string[i] = '\0'; | 257 | string[i] = '\0'; |
| 256 | } | 258 | } |
| 257 | /** | 259 | /** |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index fa64740abb59..d52c780bdb78 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -654,7 +654,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
| 654 | /* | 654 | /* |
| 655 | * You also need write access to the containing directory | 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 | smk_ad_setfield_u_fs_inode(&ad, dir); | 658 | smk_ad_setfield_u_fs_inode(&ad, dir); |
| 659 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 659 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
| 660 | } | 660 | } |
| @@ -685,7 +685,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 685 | /* | 685 | /* |
| 686 | * You also need write access to the containing directory | 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 | smk_ad_setfield_u_fs_inode(&ad, dir); | 689 | smk_ad_setfield_u_fs_inode(&ad, dir); |
| 690 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 690 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
| 691 | } | 691 | } |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 76a5dca46404..53a08b85bda4 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
| 27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
| 28 | #include <linux/audit.h> | 28 | #include <linux/audit.h> |
| 29 | #include <linux/magic.h> | ||
| 29 | #include "smack.h" | 30 | #include "smack.h" |
| 30 | 31 | ||
| 31 | /* | 32 | /* |
| @@ -50,12 +51,12 @@ enum smk_inos { | |||
| 50 | SMK_ACCESS2 = 16, /* make an access check with long labels */ | 51 | SMK_ACCESS2 = 16, /* make an access check with long labels */ |
| 51 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ | 52 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ |
| 52 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ | 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 | * List locks | 58 | * List locks |
| 57 | */ | 59 | */ |
| 58 | static DEFINE_MUTEX(smack_list_lock); | ||
| 59 | static DEFINE_MUTEX(smack_cipso_lock); | 60 | static DEFINE_MUTEX(smack_cipso_lock); |
| 60 | static DEFINE_MUTEX(smack_ambient_lock); | 61 | static DEFINE_MUTEX(smack_ambient_lock); |
| 61 | static DEFINE_MUTEX(smk_netlbladdr_lock); | 62 | static DEFINE_MUTEX(smk_netlbladdr_lock); |
| @@ -110,6 +111,13 @@ struct smack_master_list { | |||
| 110 | 111 | ||
| 111 | LIST_HEAD(smack_rule_list); | 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 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 121 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
| 114 | 122 | ||
| 115 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; | 123 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; |
| @@ -167,25 +175,28 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) | |||
| 167 | #define SMK_NETLBLADDRMIN 9 | 175 | #define SMK_NETLBLADDRMIN 9 |
| 168 | 176 | ||
| 169 | /** | 177 | /** |
| 170 | * smk_set_access - add a rule to the rule list | 178 | * smk_set_access - add a rule to the rule list or replace an old rule |
| 171 | * @srp: the new rule to add | 179 | * @srp: the rule to add or replace |
| 172 | * @rule_list: the list of rules | 180 | * @rule_list: the list of rules |
| 173 | * @rule_lock: the rule list lock | 181 | * @rule_lock: the rule list lock |
| 182 | * @global: if non-zero, indicates a global rule | ||
| 174 | * | 183 | * |
| 175 | * Looks through the current subject/object/access list for | 184 | * Looks through the current subject/object/access list for |
| 176 | * the subject/object pair and replaces the access that was | 185 | * the subject/object pair and replaces the access that was |
| 177 | * there. If the pair isn't found add it with the specified | 186 | * there. If the pair isn't found add it with the specified |
| 178 | * access. | 187 | * access. |
| 179 | * | 188 | * |
| 180 | * Returns 1 if a rule was found to exist already, 0 if it is new | ||
| 181 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails | 189 | * Returns 0 if nothing goes wrong or -ENOMEM if it fails |
| 182 | * during the allocation of the new pair to add. | 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, | 192 | static int smk_set_access(struct smack_parsed_rule *srp, |
| 185 | struct mutex *rule_lock) | 193 | struct list_head *rule_list, |
| 194 | struct mutex *rule_lock, int global) | ||
| 186 | { | 195 | { |
| 187 | struct smack_rule *sp; | 196 | struct smack_rule *sp; |
| 197 | struct smack_master_list *smlp; | ||
| 188 | int found = 0; | 198 | int found = 0; |
| 199 | int rc = 0; | ||
| 189 | 200 | ||
| 190 | mutex_lock(rule_lock); | 201 | mutex_lock(rule_lock); |
| 191 | 202 | ||
| @@ -197,23 +208,89 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |||
| 197 | if (sp->smk_object == srp->smk_object && | 208 | if (sp->smk_object == srp->smk_object && |
| 198 | sp->smk_subject == srp->smk_subject) { | 209 | sp->smk_subject == srp->smk_subject) { |
| 199 | found = 1; | 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 | break; | 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 | mutex_unlock(rule_lock); | 244 | mutex_unlock(rule_lock); |
| 245 | return rc; | ||
| 246 | } | ||
| 247 | |||
| 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; | ||
| 208 | 258 | ||
| 209 | return found; | 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 | * smk_fill_rule - Fill Smack rule from strings | 289 | * smk_fill_rule - Fill Smack rule from strings |
| 214 | * @subject: subject label string | 290 | * @subject: subject label string |
| 215 | * @object: object label string | 291 | * @object: object label string |
| 216 | * @access: access string | 292 | * @access1: access string |
| 293 | * @access2: string with permissions to be removed | ||
| 217 | * @rule: Smack rule | 294 | * @rule: Smack rule |
| 218 | * @import: if non-zero, import labels | 295 | * @import: if non-zero, import labels |
| 219 | * @len: label length limit | 296 | * @len: label length limit |
| @@ -221,8 +298,9 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |||
| 221 | * Returns 0 on success, -1 on failure | 298 | * Returns 0 on success, -1 on failure |
| 222 | */ | 299 | */ |
| 223 | static int smk_fill_rule(const char *subject, const char *object, | 300 | static int smk_fill_rule(const char *subject, const char *object, |
| 224 | const char *access, struct smack_rule *rule, | 301 | const char *access1, const char *access2, |
| 225 | int import, int len) | 302 | struct smack_parsed_rule *rule, int import, |
| 303 | int len) | ||
| 226 | { | 304 | { |
| 227 | const char *cp; | 305 | const char *cp; |
| 228 | struct smack_known *skp; | 306 | struct smack_known *skp; |
| @@ -255,36 +333,11 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
| 255 | rule->smk_object = skp->smk_known; | 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); |
| 259 | 337 | if (access2) | |
| 260 | for (cp = access; *cp != '\0'; cp++) { | 338 | rule->smk_access2 = smk_perm_from_str(access2); |
| 261 | switch (*cp) { | 339 | else |
| 262 | case '-': | 340 | rule->smk_access2 = ~rule->smk_access1; |
| 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 | 341 | ||
| 289 | return 0; | 342 | return 0; |
| 290 | } | 343 | } |
| @@ -297,30 +350,33 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
| 297 | * | 350 | * |
| 298 | * Returns 0 on success, -1 on errors. | 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 | int rc; | 356 | int rc; |
| 303 | 357 | ||
| 304 | rc = smk_fill_rule(data, data + SMK_LABELLEN, | 358 | rc = smk_fill_rule(data, data + SMK_LABELLEN, |
| 305 | data + SMK_LABELLEN + SMK_LABELLEN, rule, import, | 359 | data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule, |
| 306 | SMK_LABELLEN); | 360 | import, SMK_LABELLEN); |
| 307 | return rc; | 361 | return rc; |
| 308 | } | 362 | } |
| 309 | 363 | ||
| 310 | /** | 364 | /** |
| 311 | * smk_parse_long_rule - parse Smack rule from rule string | 365 | * smk_parse_long_rule - parse Smack rule from rule string |
| 312 | * @data: string to be parsed, null terminated | 366 | * @data: string to be parsed, null terminated |
| 313 | * @rule: Smack rule | 367 | * @rule: Will be filled with Smack parsed rule |
| 314 | * @import: if non-zero, import labels | 368 | * @import: if non-zero, import labels |
| 369 | * @change: if non-zero, data is from /smack/change-rule | ||
| 315 | * | 370 | * |
| 316 | * Returns 0 on success, -1 on failure | 371 | * Returns 0 on success, -1 on failure |
| 317 | */ | 372 | */ |
| 318 | static int smk_parse_long_rule(const char *data, struct smack_rule *rule, | 373 | static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, |
| 319 | int import) | 374 | int import, int change) |
| 320 | { | 375 | { |
| 321 | char *subject; | 376 | char *subject; |
| 322 | char *object; | 377 | char *object; |
| 323 | char *access; | 378 | char *access1; |
| 379 | char *access2; | ||
| 324 | int datalen; | 380 | int datalen; |
| 325 | int rc = -1; | 381 | int rc = -1; |
| 326 | 382 | ||
| @@ -334,14 +390,27 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule, | |||
| 334 | object = kzalloc(datalen, GFP_KERNEL); | 390 | object = kzalloc(datalen, GFP_KERNEL); |
| 335 | if (object == NULL) | 391 | if (object == NULL) |
| 336 | goto free_out_s; | 392 | goto free_out_s; |
| 337 | access = kzalloc(datalen, GFP_KERNEL); | 393 | access1 = kzalloc(datalen, GFP_KERNEL); |
| 338 | if (access == NULL) | 394 | if (access1 == NULL) |
| 339 | goto free_out_o; | 395 | goto free_out_o; |
| 396 | access2 = kzalloc(datalen, GFP_KERNEL); | ||
| 397 | if (access2 == NULL) | ||
| 398 | goto free_out_a; | ||
| 399 | |||
| 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 | } | ||
| 340 | 410 | ||
| 341 | if (sscanf(data, "%s %s %s", subject, object, access) == 3) | 411 | kfree(access2); |
| 342 | rc = smk_fill_rule(subject, object, access, rule, import, 0); | 412 | free_out_a: |
| 343 | 413 | kfree(access1); | |
| 344 | kfree(access); | ||
| 345 | free_out_o: | 414 | free_out_o: |
| 346 | kfree(object); | 415 | kfree(object); |
| 347 | free_out_s: | 416 | free_out_s: |
| @@ -351,6 +420,7 @@ free_out_s: | |||
| 351 | 420 | ||
| 352 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ | 421 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ |
| 353 | #define SMK_LONG_FMT 1 /* Variable long label format */ | 422 | #define SMK_LONG_FMT 1 /* Variable long label format */ |
| 423 | #define SMK_CHANGE_FMT 2 /* Rule modification format */ | ||
| 354 | /** | 424 | /** |
| 355 | * smk_write_rules_list - write() for any /smack rule file | 425 | * smk_write_rules_list - write() for any /smack rule file |
| 356 | * @file: file pointer, not actually used | 426 | * @file: file pointer, not actually used |
| @@ -359,22 +429,24 @@ free_out_s: | |||
| 359 | * @ppos: where to start - must be 0 | 429 | * @ppos: where to start - must be 0 |
| 360 | * @rule_list: the list of rules to write to | 430 | * @rule_list: the list of rules to write to |
| 361 | * @rule_lock: lock for the rule list | 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 | * Get one smack access rule from above. | 434 | * Get one smack access rule from above. |
| 365 | * The format for SMK_LONG_FMT is: | 435 | * The format for SMK_LONG_FMT is: |
| 366 | * "subject<whitespace>object<whitespace>access[<whitespace>...]" | 436 | * "subject<whitespace>object<whitespace>access[<whitespace>...]" |
| 367 | * The format for SMK_FIXED24_FMT is exactly: | 437 | * The format for SMK_FIXED24_FMT is exactly: |
| 368 | * "subject object rwxat" | 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 | static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | 443 | static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, |
| 371 | size_t count, loff_t *ppos, | 444 | size_t count, loff_t *ppos, |
| 372 | struct list_head *rule_list, | 445 | struct list_head *rule_list, |
| 373 | struct mutex *rule_lock, int format) | 446 | struct mutex *rule_lock, int format) |
| 374 | { | 447 | { |
| 375 | struct smack_master_list *smlp; | ||
| 376 | struct smack_known *skp; | 448 | struct smack_known *skp; |
| 377 | struct smack_rule *rule; | 449 | struct smack_parsed_rule *rule; |
| 378 | char *data; | 450 | char *data; |
| 379 | int datalen; | 451 | int datalen; |
| 380 | int rc = -EINVAL; | 452 | int rc = -EINVAL; |
| @@ -417,7 +489,11 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | |||
| 417 | * Be sure the data string is terminated. | 489 | * Be sure the data string is terminated. |
| 418 | */ | 490 | */ |
| 419 | data[count] = '\0'; | 491 | data[count] = '\0'; |
| 420 | if (smk_parse_long_rule(data, rule, 1)) | 492 | if (smk_parse_long_rule(data, rule, 1, 0)) |
| 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)) | ||
| 421 | goto out_free_rule; | 497 | goto out_free_rule; |
| 422 | } else { | 498 | } else { |
| 423 | /* | 499 | /* |
| @@ -437,22 +513,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | |||
| 437 | rule_lock = &skp->smk_rules_lock; | 513 | rule_lock = &skp->smk_rules_lock; |
| 438 | } | 514 | } |
| 439 | 515 | ||
| 440 | rc = count; | 516 | rc = smk_set_access(rule, rule_list, rule_lock, load); |
| 441 | /* | 517 | if (rc == 0) { |
| 442 | * If this is a global as opposed to self and a new rule | 518 | rc = count; |
| 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 | } | ||
| 456 | goto out; | 519 | goto out; |
| 457 | } | 520 | } |
| 458 | 521 | ||
| @@ -1774,7 +1837,7 @@ static const struct file_operations smk_load_self_ops = { | |||
| 1774 | static ssize_t smk_user_access(struct file *file, const char __user *buf, | 1837 | static ssize_t smk_user_access(struct file *file, const char __user *buf, |
| 1775 | size_t count, loff_t *ppos, int format) | 1838 | size_t count, loff_t *ppos, int format) |
| 1776 | { | 1839 | { |
| 1777 | struct smack_rule rule; | 1840 | struct smack_parsed_rule rule; |
| 1778 | char *data; | 1841 | char *data; |
| 1779 | char *cod; | 1842 | char *cod; |
| 1780 | int res; | 1843 | int res; |
| @@ -1796,14 +1859,14 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, | |||
| 1796 | return -ENOMEM; | 1859 | return -ENOMEM; |
| 1797 | memcpy(cod, data, count); | 1860 | memcpy(cod, data, count); |
| 1798 | cod[count] = '\0'; | 1861 | cod[count] = '\0'; |
| 1799 | res = smk_parse_long_rule(cod, &rule, 0); | 1862 | res = smk_parse_long_rule(cod, &rule, 0, 0); |
| 1800 | kfree(cod); | 1863 | kfree(cod); |
| 1801 | } | 1864 | } |
| 1802 | 1865 | ||
| 1803 | if (res) | 1866 | if (res) |
| 1804 | return -EINVAL; | 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 | NULL); | 1870 | NULL); |
| 1808 | data[0] = res == 0 ? '1' : '0'; | 1871 | data[0] = res == 0 ? '1' : '0'; |
| 1809 | data[1] = '\0'; | 1872 | data[1] = '\0'; |
| @@ -2035,10 +2098,8 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, | |||
| 2035 | } | 2098 | } |
| 2036 | 2099 | ||
| 2037 | skp = smk_find_entry(cp); | 2100 | skp = smk_find_entry(cp); |
| 2038 | if (skp == NULL) { | 2101 | if (skp == NULL) |
| 2039 | rc = -EINVAL; | ||
| 2040 | goto free_out; | 2102 | goto free_out; |
| 2041 | } | ||
| 2042 | 2103 | ||
| 2043 | rule_list = &skp->smk_rules; | 2104 | rule_list = &skp->smk_rules; |
| 2044 | rule_lock = &skp->smk_rules_lock; | 2105 | rule_lock = &skp->smk_rules_lock; |
| @@ -2077,6 +2138,33 @@ static int smk_init_sysfs(void) | |||
| 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 | * smk_fill_super - fill the /smackfs superblock | 2168 | * smk_fill_super - fill the /smackfs superblock |
| 2081 | * @sb: the empty superblock | 2169 | * @sb: the empty superblock |
| 2082 | * @data: unused | 2170 | * @data: unused |
| @@ -2125,6 +2213,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2125 | [SMK_REVOKE_SUBJ] = { | 2213 | [SMK_REVOKE_SUBJ] = { |
| 2126 | "revoke-subject", &smk_revoke_subj_ops, | 2214 | "revoke-subject", &smk_revoke_subj_ops, |
| 2127 | S_IRUGO|S_IWUSR}, | 2215 | S_IRUGO|S_IWUSR}, |
| 2216 | [SMK_CHANGE_RULE] = { | ||
| 2217 | "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, | ||
| 2128 | /* last one */ | 2218 | /* last one */ |
| 2129 | {""} | 2219 | {""} |
| 2130 | }; | 2220 | }; |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index a2ee362546ab..f0b756e27fed 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
| @@ -536,7 +536,7 @@ static struct security_operations tomoyo_security_ops = { | |||
| 536 | }; | 536 | }; |
| 537 | 537 | ||
| 538 | /* Lock for GC. */ | 538 | /* Lock for GC. */ |
| 539 | struct srcu_struct tomoyo_ss; | 539 | DEFINE_SRCU(tomoyo_ss); |
| 540 | 540 | ||
| 541 | /** | 541 | /** |
| 542 | * tomoyo_init - Register TOMOYO Linux as a LSM module. | 542 | * tomoyo_init - Register TOMOYO Linux as a LSM module. |
| @@ -550,8 +550,7 @@ static int __init tomoyo_init(void) | |||
| 550 | if (!security_module_enable(&tomoyo_security_ops)) | 550 | if (!security_module_enable(&tomoyo_security_ops)) |
| 551 | return 0; | 551 | return 0; |
| 552 | /* register ourselves with the security framework */ | 552 | /* register ourselves with the security framework */ |
| 553 | if (register_security(&tomoyo_security_ops) || | 553 | if (register_security(&tomoyo_security_ops)) |
| 554 | init_srcu_struct(&tomoyo_ss)) | ||
| 555 | panic("Failure registering TOMOYO Linux"); | 554 | panic("Failure registering TOMOYO Linux"); |
| 556 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 555 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
| 557 | cred->security = &tomoyo_kernel_domain; | 556 | cred->security = &tomoyo_kernel_domain; |
