Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Nov 2017 18:30:44 +0000 (10:30 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Nov 2017 18:30:44 +0000 (10:30 -0800)
Pull general security subsystem updates from James Morris:
 "TPM (from Jarkko):
   - essential clean up for tpm_crb so that ARM64 and x86 versions do
     not distract each other as much as before

   - /dev/tpm0 rejects now too short writes (shorter buffer than
     specified in the command header

   - use DMA-safe buffer in tpm_tis_spi

   - otherwise mostly minor fixes.

  Smack:
   - base support for overlafs

  Capabilities:
   - BPRM_FCAPS fixes, from Richard Guy Briggs:

     The audit subsystem is adding a BPRM_FCAPS record when auditing
     setuid application execution (SYSCALL execve). This is not expected
     as it was supposed to be limited to when the file system actually
     had capabilities in an extended attribute. It lists all
     capabilities making the event really ugly to parse what is
     happening. The PATH record correctly records the setuid bit and
     owner. Suppress the BPRM_FCAPS record on set*id.

  TOMOYO:
   - Y2038 timestamping fixes"

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (28 commits)
  MAINTAINERS: update the IMA, EVM, trusted-keys, encrypted-keys entries
  Smack: Base support for overlayfs
  MAINTAINERS: remove David Safford as maintainer for encrypted+trusted keys
  tomoyo: fix timestamping for y2038
  capabilities: audit log other surprising conditions
  capabilities: fix logic for effective root or real root
  capabilities: invert logic for clarity
  capabilities: remove a layer of conditional logic
  capabilities: move audit log decision to function
  capabilities: use intuitive names for id changes
  capabilities: use root_priveleged inline to clarify logic
  capabilities: rename has_cap to has_fcap
  capabilities: intuitive names for cap gain status
  capabilities: factor out cap_bprm_set_creds privileged root
  tpm, tpm_tis: use ARRAY_SIZE() to define TPM_HID_USR_IDX
  tpm: fix duplicate inline declaration specifier
  tpm: fix type of a local variables in tpm_tis_spi.c
  tpm: fix type of a local variable in tpm2_map_command()
  tpm: fix type of a local variable in tpm2_get_cc_attrs_tbl()
  tpm-dev-common: Reject too short writes
  ...

17 files changed:
MAINTAINERS
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm-sysfs.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm2-space.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_core.h
drivers/char/tpm/tpm_tis_spi.c
security/commoncap.c
security/smack/smack_lsm.c
security/tomoyo/audit.c
security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/util.c

index 779fa6dde58bd3404267c6d1296d99c6e55422ee..026644adfd8f65ca61b57b8a6c9e1a6bb55a2a7f 100644 (file)
@@ -5219,8 +5219,7 @@ F:        fs/ext4/
 
 Extended Verification Module (EVM)
 M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
-L:     linux-ima-devel@lists.sourceforge.net
-L:     linux-security-module@vger.kernel.org
+L:     linux-integrity@vger.kernel.org
 S:     Supported
 F:     security/integrity/evm/
 
@@ -6847,9 +6846,7 @@ L:        linux-crypto@vger.kernel.org
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
 M:     Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
-L:     linux-ima-devel@lists.sourceforge.net
-L:     linux-ima-user@lists.sourceforge.net
-L:     linux-security-module@vger.kernel.org
+L:     linux-integrity@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
 S:     Supported
 F:     security/integrity/ima/
@@ -7632,8 +7629,7 @@ F:        kernel/kexec*
 
 KEYS-ENCRYPTED
 M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
-M:     David Safford <safford@us.ibm.com>
-L:     linux-security-module@vger.kernel.org
+L:     linux-integrity@vger.kernel.org
 L:     keyrings@vger.kernel.org
 S:     Supported
 F:     Documentation/security/keys/trusted-encrypted.rst
@@ -7641,9 +7637,8 @@ F:        include/keys/encrypted-type.h
 F:     security/keys/encrypted-keys/
 
 KEYS-TRUSTED
-M:     David Safford <safford@us.ibm.com>
 M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
-L:     linux-security-module@vger.kernel.org
+L:     linux-integrity@vger.kernel.org
 L:     keyrings@vger.kernel.org
 S:     Supported
 F:     Documentation/security/keys/trusted-encrypted.rst
index 610638a80383d4a104a6fe1ec42479722f222f49..461bf0b8a09473dbadc89b9259473dc36be2cd77 100644 (file)
@@ -110,6 +110,12 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
                return -EFAULT;
        }
 
+       if (in_size < 6 ||
+           in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) {
+               mutex_unlock(&priv->buffer_mutex);
+               return -EINVAL;
+       }
+
        /* atomic tpm command send and result receive. We only hold the ops
         * lock during this period so that the tpm can be unregistered even if
         * the char dev is held open.
index 86f38d239476ab00a70db97640e0ff843c7dd3de..83a77a4455380276ef8d4786cac2c330f3242460 100644 (file)
 #include <linux/device.h>
 #include "tpm.h"
 
-#define READ_PUBEK_RESULT_SIZE 314
+struct tpm_readpubek_out {
+       u8 algorithm[4];
+       u8 encscheme[2];
+       u8 sigscheme[2];
+       __be32 paramsize;
+       u8 parameters[12];
+       __be32 keysize;
+       u8 modulus[256];
+       u8 checksum[20];
+} __packed;
+
 #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
 #define TPM_ORD_READPUBEK 124
-static const struct tpm_input_header tpm_readpubek_header = {
-       .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-       .length = cpu_to_be32(30),
-       .ordinal = cpu_to_be32(TPM_ORD_READPUBEK)
-};
+
 static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
-       u8 *data;
-       struct tpm_cmd_t tpm_cmd;
-       ssize_t err;
-       int i, rc;
+       struct tpm_buf tpm_buf;
+       struct tpm_readpubek_out *out;
+       ssize_t rc;
+       int i;
        char *str = buf;
        struct tpm_chip *chip = to_tpm_chip(dev);
+       char anti_replay[20];
 
-       memset(&tpm_cmd, 0, sizeof(tpm_cmd));
-
-       tpm_cmd.header.in = tpm_readpubek_header;
-       err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
-                              READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
-                              "attempting to read the PUBEK");
-       if (err)
-               goto out;
-
-       /*
-          ignore header 10 bytes
-          algorithm 32 bits (1 == RSA )
-          encscheme 16 bits
-          sigscheme 16 bits
-          parameters (RSA 12->bytes: keybit, #primes, expbit)
-          keylenbytes 32 bits
-          256 byte modulus
-          ignore checksum 20 bytes
-        */
-       data = tpm_cmd.params.readpubek_out_buffer;
+       memset(&anti_replay, 0, sizeof(anti_replay));
+
+       rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK);
+       if (rc)
+               return rc;
+
+       tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay));
+
+       rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE,
+                             READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
+                             "attempting to read the PUBEK");
+       if (rc) {
+               tpm_buf_destroy(&tpm_buf);
+               return 0;
+       }
+
+       out = (struct tpm_readpubek_out *)&tpm_buf.data[10];
        str +=
            sprintf(str,
                    "Algorithm: %02X %02X %02X %02X\n"
@@ -68,21 +72,26 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
                    "%02X %02X %02X %02X\n"
                    "Modulus length: %d\n"
                    "Modulus:\n",
-                   data[0], data[1], data[2], data[3],
-                   data[4], data[5],
-                   data[6], data[7],
-                   data[12], data[13], data[14], data[15],
-                   data[16], data[17], data[18], data[19],
-                   data[20], data[21], data[22], data[23],
-                   be32_to_cpu(*((__be32 *) (data + 24))));
+                   out->algorithm[0], out->algorithm[1], out->algorithm[2],
+                   out->algorithm[3],
+                   out->encscheme[0], out->encscheme[1],
+                   out->sigscheme[0], out->sigscheme[1],
+                   out->parameters[0], out->parameters[1],
+                   out->parameters[2], out->parameters[3],
+                   out->parameters[4], out->parameters[5],
+                   out->parameters[6], out->parameters[7],
+                   out->parameters[8], out->parameters[9],
+                   out->parameters[10], out->parameters[11],
+                   be32_to_cpu(out->keysize));
 
        for (i = 0; i < 256; i++) {
-               str += sprintf(str, "%02X ", data[i + 28]);
+               str += sprintf(str, "%02X ", out->modulus[i]);
                if ((i + 1) % 16 == 0)
                        str += sprintf(str, "\n");
        }
-out:
+
        rc = str - buf;
+       tpm_buf_destroy(&tpm_buf);
        return rc;
 }
 static DEVICE_ATTR_RO(pubek);
index 2d5466a72e40f82b3272b857b74a1f822f82b966..528cffbd49d376603eaf80ccb0a4865f0c742d0b 100644 (file)
@@ -345,17 +345,6 @@ enum tpm_sub_capabilities {
        TPM_CAP_PROP_TIS_DURATION = 0x120,
 };
 
-struct tpm_readpubek_params_out {
-       u8      algorithm[4];
-       u8      encscheme[2];
-       u8      sigscheme[2];
-       __be32  paramsize;
-       u8      parameters[12]; /*assuming RSA*/
-       __be32  keysize;
-       u8      modulus[256];
-       u8      checksum[20];
-} __packed;
-
 typedef union {
        struct  tpm_input_header in;
        struct  tpm_output_header out;
@@ -385,8 +374,6 @@ struct tpm_getrandom_in {
 } __packed;
 
 typedef union {
-       struct  tpm_readpubek_params_out readpubek_out;
-       u8      readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
        struct  tpm_pcrread_in  pcrread_in;
        struct  tpm_pcrread_out pcrread_out;
        struct  tpm_getrandom_in getrandom_in;
@@ -557,7 +544,7 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
 }
 #endif
 
-static inline inline u32 tpm2_rc_value(u32 rc)
+static inline u32 tpm2_rc_value(u32 rc)
 {
        return (rc & BIT(7)) ? rc & 0xff : rc;
 }
index e1a41b788f081c829ad0d0353ac7d3622752c82f..f40d20671a78fd8469c87074f18b5e81b5d3536d 100644 (file)
@@ -834,72 +834,43 @@ static const struct tpm_input_header tpm2_selftest_header = {
 };
 
 /**
- * tpm2_continue_selftest() - start a self test
- *
- * @chip: TPM chip to use
- * @full: test all commands instead of testing only those that were not
- *        previously tested.
- *
- * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING.
- */
-static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
-{
-       int rc;
-       struct tpm2_cmd cmd;
-
-       cmd.header.in = tpm2_selftest_header;
-       cmd.params.selftest_in.full_test = full;
-
-       rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
-                             "continue selftest");
-
-       /* At least some prototype chips seem to give RC_TESTING error
-        * immediately. This is a workaround for that.
-        */
-       if (rc == TPM2_RC_TESTING) {
-               dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
-               rc = 0;
-       }
-
-       return rc;
-}
-
-/**
- * tpm2_do_selftest() - run a full self test
+ * tpm2_do_selftest() - ensure that all self tests have passed
  *
  * @chip: TPM chip to use
  *
  * Return: Same as with tpm_transmit_cmd.
  *
- * During the self test TPM2 commands return with the error code RC_TESTING.
- * Waiting is done by issuing PCR read until it executes successfully.
+ * The TPM can either run all self tests synchronously and then return
+ * RC_SUCCESS once all tests were successful. Or it can choose to run the tests
+ * asynchronously and return RC_TESTING immediately while the self tests still
+ * execute in the background. This function handles both cases and waits until
+ * all tests have completed.
  */
 static int tpm2_do_selftest(struct tpm_chip *chip)
 {
        int rc;
-       unsigned int loops;
-       unsigned int delay_msec = 100;
-       unsigned long duration;
-       int i;
-
-       duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
+       unsigned int delay_msec = 20;
+       long duration;
+       struct tpm2_cmd cmd;
 
-       loops = jiffies_to_msecs(duration) / delay_msec;
+       duration = jiffies_to_msecs(
+               tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST));
 
-       rc = tpm2_start_selftest(chip, true);
-       if (rc)
-               return rc;
+       while (duration > 0) {
+               cmd.header.in = tpm2_selftest_header;
+               cmd.params.selftest_in.full_test = 0;
 
-       for (i = 0; i < loops; i++) {
-               /* Attempt to read a PCR value */
-               rc = tpm2_pcr_read(chip, 0, NULL);
-               if (rc < 0)
-                       break;
+               rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
+                                     0, 0, "continue selftest");
 
                if (rc != TPM2_RC_TESTING)
                        break;
 
                tpm_msleep(delay_msec);
+               duration -= delay_msec;
+
+               /* wait longer the next round */
+               delay_msec *= 2;
        }
 
        return rc;
@@ -1009,7 +980,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
 {
        struct tpm_buf buf;
        u32 nr_commands;
-       u32 *attrs;
+       __be32 *attrs;
        u32 cc;
        int i;
        int rc;
@@ -1049,7 +1020,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
 
        chip->nr_commands = nr_commands;
 
-       attrs = (u32 *)&buf.data[TPM_HEADER_SIZE + 9];
+       attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9];
        for (i = 0; i < nr_commands; i++, attrs++) {
                chip->cc_attrs_tbl[i] = be32_to_cpup(attrs);
                cc = chip->cc_attrs_tbl[i] & 0xFFFF;
index e2e059d8ffec0c16ec9e106d6c848a036857295f..4e4014eabdb9c34776d1fbd71c3a8747fcca8c6f 100644 (file)
@@ -242,7 +242,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd)
        struct tpm_space *space = &chip->work_space;
        unsigned int nr_handles;
        u32 attrs;
-       u32 *handle;
+       __be32 *handle;
        int i;
 
        i = tpm2_find_cc(chip, cc);
@@ -252,7 +252,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd)
        attrs = chip->cc_attrs_tbl[i];
        nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
 
-       handle = (u32 *)&cmd[TPM_HEADER_SIZE];
+       handle = (__be32 *)&cmd[TPM_HEADER_SIZE];
        for (i = 0; i < nr_handles; i++, handle++) {
                if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) {
                        if (!tpm2_map_to_phandle(space, handle))
index 8f0a98dea327a5bc90d7fcf3529c3701d17abd6b..7b3c2a8aa9defc33e4189658e797dbecdb38149f 100644 (file)
@@ -92,14 +92,9 @@ enum crb_status {
        CRB_DRV_STS_COMPLETE    = BIT(0),
 };
 
-enum crb_flags {
-       CRB_FL_ACPI_START       = BIT(0),
-       CRB_FL_CRB_START        = BIT(1),
-       CRB_FL_CRB_SMC_START    = BIT(2),
-};
-
 struct crb_priv {
-       unsigned int flags;
+       u32 sm;
+       const char *hid;
        void __iomem *iobase;
        struct crb_regs_head __iomem *regs_h;
        struct crb_regs_tail __iomem *regs_t;
@@ -128,14 +123,16 @@ struct tpm2_crb_smc {
  * Anyhow, we do not wait here as a consequent CMD_READY request
  * will be handled correctly even if idle was not completed.
  *
- * The function does nothing for devices with ACPI-start method.
+ * The function does nothing for devices with ACPI-start method
+ * or SMC-start method.
  *
  * Return: 0 always
  */
 static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
 {
-       if ((priv->flags & CRB_FL_ACPI_START) ||
-           (priv->flags & CRB_FL_CRB_SMC_START))
+       if ((priv->sm == ACPI_TPM2_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
                return 0;
 
        iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
@@ -174,14 +171,16 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
  * The device should respond within TIMEOUT_C.
  *
  * The function does nothing for devices with ACPI-start method
+ * or SMC-start method.
  *
  * Return: 0 on success -ETIME on timeout;
  */
 static int __maybe_unused crb_cmd_ready(struct device *dev,
                                        struct crb_priv *priv)
 {
-       if ((priv->flags & CRB_FL_ACPI_START) ||
-           (priv->flags & CRB_FL_CRB_SMC_START))
+       if ((priv->sm == ACPI_TPM2_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
                return 0;
 
        iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
@@ -325,13 +324,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
        /* Make sure that cmd is populated before issuing start. */
        wmb();
 
-       if (priv->flags & CRB_FL_CRB_START)
+       /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
+        * report only ACPI start but in practice seems to require both
+        * CRB start, hence invoking CRB start method if hid == MSFT0101.
+        */
+       if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) ||
+           (priv->sm == ACPI_TPM2_MEMORY_MAPPED) ||
+           (!strcmp(priv->hid, "MSFT0101")))
                iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
 
-       if (priv->flags & CRB_FL_ACPI_START)
+       if ((priv->sm == ACPI_TPM2_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD))
                rc = crb_do_acpi_start(chip);
 
-       if (priv->flags & CRB_FL_CRB_SMC_START) {
+       if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) {
                iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
                rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id);
        }
@@ -345,7 +351,9 @@ static void crb_cancel(struct tpm_chip *chip)
 
        iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
 
-       if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip))
+       if (((priv->sm == ACPI_TPM2_START_METHOD) ||
+           (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) &&
+            crb_do_acpi_start(chip))
                dev_err(&chip->dev, "ACPI Start failed\n");
 }
 
@@ -458,7 +466,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
         * the control area, as one nice sane region except for some older
         * stuff that puts the control area outside the ACPI IO region.
         */
-       if (!(priv->flags & CRB_FL_ACPI_START)) {
+       if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) ||
+           (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) {
                if (buf->control_address == io_res.start +
                    sizeof(*priv->regs_h))
                        priv->regs_h = priv->iobase;
@@ -552,18 +561,6 @@ static int crb_acpi_add(struct acpi_device *device)
        if (!priv)
                return -ENOMEM;
 
-       /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
-        * report only ACPI start but in practice seems to require both
-        * ACPI start and CRB start.
-        */
-       if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED ||
-           !strcmp(acpi_device_hid(device), "MSFT0101"))
-               priv->flags |= CRB_FL_CRB_START;
-
-       if (sm == ACPI_TPM2_START_METHOD ||
-           sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)
-               priv->flags |= CRB_FL_ACPI_START;
-
        if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) {
                if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) {
                        dev_err(dev,
@@ -574,9 +571,11 @@ static int crb_acpi_add(struct acpi_device *device)
                }
                crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf));
                priv->smc_func_id = crb_smc->smc_func_id;
-               priv->flags |= CRB_FL_CRB_SMC_START;
        }
 
+       priv->sm = sm;
+       priv->hid = acpi_device_hid(device);
+
        rc = crb_map_io(device, priv, buf);
        if (rc)
                return rc;
index 7e55aa9ce680cbc6cd2802710625e41775c9b2e9..e2d1055fb814c3e7d2e8b2ed846e6e03d774892c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/freezer.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/kernel.h>
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
@@ -223,7 +224,7 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 }
 
 static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
-                              u8 *value)
+                              const u8 *value)
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
@@ -365,7 +366,7 @@ static struct pnp_driver tis_pnp_driver = {
        },
 };
 
-#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+#define TIS_HID_USR_IDX (ARRAY_SIZE(tpm_pnp_tbl) - 2)
 module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
                    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
index 63bc6c3b949e51406527a484d356e24959ed9615..fdde971bc8108b574eed3a9f1a500904207e3a1c 100644 (file)
@@ -252,7 +252,7 @@ out:
  * tpm.c can skip polling for the data to be available as the interrupt is
  * waited for here
  */
-static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
+static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        int rc, status, burstcnt;
@@ -343,7 +343,7 @@ static void disable_interrupts(struct tpm_chip *chip)
  * tpm.c can skip polling for the data to be available as the interrupt is
  * waited for here
  */
-static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
+static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        int rc;
@@ -445,7 +445,7 @@ static int probe_itpm(struct tpm_chip *chip)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        int rc = 0;
-       u8 cmd_getticks[] = {
+       static const u8 cmd_getticks[] = {
                0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
                0x00, 0x00, 0x00, 0xf1
        };
index e2212f021a02eb67db9be8bf479edaa97d8b516d..6bbac319ff3bfe46169a948775e323e72f172893 100644 (file)
@@ -98,7 +98,7 @@ struct tpm_tis_phy_ops {
        int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
                          u8 *result);
        int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
-                          u8 *value);
+                          const u8 *value);
        int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
        int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
        int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
@@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr,
 }
 
 static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr,
-                                     u16 len, u8 *value)
+                                     u16 len, const u8 *value)
 {
        return data->phy_ops->write_bytes(data, addr, len, value);
 }
index 88fe72ae967fec1a29ed309a26d823f41a2ee5d4..424ff2fde1f2d60e3e42298153cffbf16758cedd 100644 (file)
@@ -46,9 +46,7 @@
 struct tpm_tis_spi_phy {
        struct tpm_tis_data priv;
        struct spi_device *spi_device;
-
-       u8 tx_buf[4];
-       u8 rx_buf[4];
+       u8 *iobuf;
 };
 
 static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
@@ -57,7 +55,7 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da
 }
 
 static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
-                               u8 *buffer, u8 direction)
+                               u8 *in, const u8 *out)
 {
        struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
        int ret = 0;
@@ -71,14 +69,14 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
        while (len) {
                transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
 
-               phy->tx_buf[0] = direction | (transfer_len - 1);
-               phy->tx_buf[1] = 0xd4;
-               phy->tx_buf[2] = addr >> 8;
-               phy->tx_buf[3] = addr;
+               phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+               phy->iobuf[1] = 0xd4;
+               phy->iobuf[2] = addr >> 8;
+               phy->iobuf[3] = addr;
 
                memset(&spi_xfer, 0, sizeof(spi_xfer));
-               spi_xfer.tx_buf = phy->tx_buf;
-               spi_xfer.rx_buf = phy->rx_buf;
+               spi_xfer.tx_buf = phy->iobuf;
+               spi_xfer.rx_buf = phy->iobuf;
                spi_xfer.len = 4;
                spi_xfer.cs_change = 1;
 
@@ -88,9 +86,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                if (ret < 0)
                        goto exit;
 
-               if ((phy->rx_buf[3] & 0x01) == 0) {
+               if ((phy->iobuf[3] & 0x01) == 0) {
                        // handle SPI wait states
-                       phy->tx_buf[0] = 0;
+                       phy->iobuf[0] = 0;
 
                        for (i = 0; i < TPM_RETRY; i++) {
                                spi_xfer.len = 1;
@@ -99,7 +97,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                                ret = spi_sync_locked(phy->spi_device, &m);
                                if (ret < 0)
                                        goto exit;
-                               if (phy->rx_buf[0] & 0x01)
+                               if (phy->iobuf[0] & 0x01)
                                        break;
                        }
 
@@ -113,12 +111,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                spi_xfer.len = transfer_len;
                spi_xfer.delay_usecs = 5;
 
-               if (direction) {
+               if (in) {
                        spi_xfer.tx_buf = NULL;
-                       spi_xfer.rx_buf = buffer;
-               } else {
-                       spi_xfer.tx_buf = buffer;
+               } else if (out) {
                        spi_xfer.rx_buf = NULL;
+                       memcpy(phy->iobuf, out, transfer_len);
+                       out += transfer_len;
                }
 
                spi_message_init(&m);
@@ -127,8 +125,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
                if (ret < 0)
                        goto exit;
 
+               if (in) {
+                       memcpy(in, phy->iobuf, transfer_len);
+                       in += transfer_len;
+               }
+
                len -= transfer_len;
-               buffer += transfer_len;
        }
 
 exit:
@@ -139,40 +141,51 @@ exit:
 static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
                                  u16 len, u8 *result)
 {
-       return tpm_tis_spi_transfer(data, addr, len, result, 0x80);
+       return tpm_tis_spi_transfer(data, addr, len, result, NULL);
 }
 
 static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
-                                  u16 len, u8 *value)
+                                  u16 len, const u8 *value)
 {
-       return tpm_tis_spi_transfer(data, addr, len, value, 0);
+       return tpm_tis_spi_transfer(data, addr, len, NULL, value);
 }
 
 static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
 {
+       __le16 result_le;
        int rc;
 
-       rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), (u8 *)result);
+       rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
+                                      (u8 *)&result_le);
        if (!rc)
-               *result = le16_to_cpu(*result);
+               *result = le16_to_cpu(result_le);
+
        return rc;
 }
 
 static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
 {
+       __le32 result_le;
        int rc;
 
-       rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), (u8 *)result);
+       rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
+                                      (u8 *)&result_le);
        if (!rc)
-               *result = le32_to_cpu(*result);
+               *result = le32_to_cpu(result_le);
+
        return rc;
 }
 
 static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
 {
-       value = cpu_to_le32(value);
-       return data->phy_ops->write_bytes(data, addr, sizeof(u32),
-                                          (u8 *)&value);
+       __le32 value_le;
+       int rc;
+
+       value_le = cpu_to_le32(value);
+       rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
+                                       (u8 *)&value_le);
+
+       return rc;
 }
 
 static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
@@ -194,6 +207,10 @@ static int tpm_tis_spi_probe(struct spi_device *dev)
 
        phy->spi_device = dev;
 
+       phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+       if (!phy->iobuf)
+               return -ENOMEM;
+
        return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops,
                                 NULL);
 }
index fc46f5b85251049265a53929e37d5822240a64e3..4f8e0934095679f71e9674d4a567c6c1fe492f9e 100644 (file)
@@ -536,7 +536,7 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size)
 static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
                                          struct linux_binprm *bprm,
                                          bool *effective,
-                                         bool *has_cap)
+                                         bool *has_fcap)
 {
        struct cred *new = bprm->cred;
        unsigned i;
@@ -546,7 +546,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
                *effective = true;
 
        if (caps->magic_etc & VFS_CAP_REVISION_MASK)
-               *has_cap = true;
+               *has_fcap = true;
 
        CAP_FOR_EACH_U32(i) {
                __u32 permitted = caps->permitted.cap[i];
@@ -653,7 +653,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
  * its xattrs and, if present, apply them to the proposed credentials being
  * constructed by execve().
  */
-static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap)
+static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_fcap)
 {
        int rc = 0;
        struct cpu_vfs_cap_data vcaps;
@@ -684,7 +684,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
                goto out;
        }
 
-       rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_cap);
+       rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_fcap);
        if (rc == -EINVAL)
                printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
                       __func__, rc, bprm->filename);
@@ -696,6 +696,115 @@ out:
        return rc;
 }
 
+static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); }
+
+static inline bool __is_real(kuid_t uid, struct cred *cred)
+{ return uid_eq(cred->uid, uid); }
+
+static inline bool __is_eff(kuid_t uid, struct cred *cred)
+{ return uid_eq(cred->euid, uid); }
+
+static inline bool __is_suid(kuid_t uid, struct cred *cred)
+{ return !__is_real(uid, cred) && __is_eff(uid, cred); }
+
+/*
+ * handle_privileged_root - Handle case of privileged root
+ * @bprm: The execution parameters, including the proposed creds
+ * @has_fcap: Are any file capabilities set?
+ * @effective: Do we have effective root privilege?
+ * @root_uid: This namespace' root UID WRT initial USER namespace
+ *
+ * Handle the case where root is privileged and hasn't been neutered by
+ * SECURE_NOROOT.  If file capabilities are set, they won't be combined with
+ * set UID root and nothing is changed.  If we are root, cap_permitted is
+ * updated.  If we have become set UID root, the effective bit is set.
+ */
+static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
+                                  bool *effective, kuid_t root_uid)
+{
+       const struct cred *old = current_cred();
+       struct cred *new = bprm->cred;
+
+       if (!root_privileged())
+               return;
+       /*
+        * If the legacy file capability is set, then don't set privs
+        * for a setuid root binary run by a non-root user.  Do set it
+        * for a root user just to cause least surprise to an admin.
+        */
+       if (has_fcap && __is_suid(root_uid, new)) {
+               warn_setuid_and_fcaps_mixed(bprm->filename);
+               return;
+       }
+       /*
+        * To support inheritance of root-permissions and suid-root
+        * executables under compatibility mode, we override the
+        * capability sets for the file.
+        */
+       if (__is_eff(root_uid, new) || __is_real(root_uid, new)) {
+               /* pP' = (cap_bset & ~0) | (pI & ~0) */
+               new->cap_permitted = cap_combine(old->cap_bset,
+                                                old->cap_inheritable);
+       }
+       /*
+        * If only the real uid is 0, we do not set the effective bit.
+        */
+       if (__is_eff(root_uid, new))
+               *effective = true;
+}
+
+#define __cap_gained(field, target, source) \
+       !cap_issubset(target->cap_##field, source->cap_##field)
+#define __cap_grew(target, source, cred) \
+       !cap_issubset(cred->cap_##target, cred->cap_##source)
+#define __cap_full(field, cred) \
+       cap_issubset(CAP_FULL_SET, cred->cap_##field)
+
+static inline bool __is_setuid(struct cred *new, const struct cred *old)
+{ return !uid_eq(new->euid, old->uid); }
+
+static inline bool __is_setgid(struct cred *new, const struct cred *old)
+{ return !gid_eq(new->egid, old->gid); }
+
+/*
+ * 1) Audit candidate if current->cap_effective is set
+ *
+ * We do not bother to audit if 3 things are true:
+ *   1) cap_effective has all caps
+ *   2) we became root *OR* are were already root
+ *   3) root is supposed to have all caps (SECURE_NOROOT)
+ * Since this is just a normal root execing a process.
+ *
+ * Number 1 above might fail if you don't have a full bset, but I think
+ * that is interesting information to audit.
+ *
+ * A number of other conditions require logging:
+ * 2) something prevented setuid root getting all caps
+ * 3) non-setuid root gets fcaps
+ * 4) non-setuid root gets ambient
+ */
+static inline bool nonroot_raised_pE(struct cred *new, const struct cred *old,
+                                    kuid_t root, bool has_fcap)
+{
+       bool ret = false;
+
+       if ((__cap_grew(effective, ambient, new) &&
+            !(__cap_full(effective, new) &&
+              (__is_eff(root, new) || __is_real(root, new)) &&
+              root_privileged())) ||
+           (root_privileged() &&
+            __is_suid(root, new) &&
+            !__cap_full(effective, new)) ||
+           (!__is_setuid(new, old) &&
+            ((has_fcap &&
+              __cap_gained(permitted, new, old)) ||
+             __cap_gained(ambient, new, old))))
+
+               ret = true;
+
+       return ret;
+}
+
 /**
  * cap_bprm_set_creds - Set up the proposed credentials for execve().
  * @bprm: The execution parameters, including the proposed creds
@@ -708,61 +817,33 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
 {
        const struct cred *old = current_cred();
        struct cred *new = bprm->cred;
-       bool effective, has_cap = false, is_setid;
+       bool effective = false, has_fcap = false, is_setid;
        int ret;
        kuid_t root_uid;
 
        if (WARN_ON(!cap_ambient_invariant_ok(old)))
                return -EPERM;
 
-       effective = false;
-       ret = get_file_caps(bprm, &effective, &has_cap);
+       ret = get_file_caps(bprm, &effective, &has_fcap);
        if (ret < 0)
                return ret;
 
        root_uid = make_kuid(new->user_ns, 0);
 
-       if (!issecure(SECURE_NOROOT)) {
-               /*
-                * If the legacy file capability is set, then don't set privs
-                * for a setuid root binary run by a non-root user.  Do set it
-                * for a root user just to cause least surprise to an admin.
-                */
-               if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) {
-                       warn_setuid_and_fcaps_mixed(bprm->filename);
-                       goto skip;
-               }
-               /*
-                * To support inheritance of root-permissions and suid-root
-                * executables under compatibility mode, we override the
-                * capability sets for the file.
-                *
-                * If only the real uid is 0, we do not set the effective bit.
-                */
-               if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) {
-                       /* pP' = (cap_bset & ~0) | (pI & ~0) */
-                       new->cap_permitted = cap_combine(old->cap_bset,
-                                                        old->cap_inheritable);
-               }
-               if (uid_eq(new->euid, root_uid))
-                       effective = true;
-       }
-skip:
+       handle_privileged_root(bprm, has_fcap, &effective, root_uid);
 
        /* if we have fs caps, clear dangerous personality flags */
-       if (!cap_issubset(new->cap_permitted, old->cap_permitted))
+       if (__cap_gained(permitted, new, old))
                bprm->per_clear |= PER_CLEAR_ON_SETID;
 
-
        /* Don't let someone trace a set[ug]id/setpcap binary with the revised
         * credentials unless they have the appropriate permit.
         *
         * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
         */
-       is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
+       is_setid = __is_setuid(new, old) || __is_setgid(new, old);
 
-       if ((is_setid ||
-            !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
+       if ((is_setid || __cap_gained(permitted, new, old)) &&
            ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) ||
             !ptracer_capable(current, new->user_ns))) {
                /* downgrade; they get no more than they had, and maybe less */
@@ -779,7 +860,7 @@ skip:
        new->sgid = new->fsgid = new->egid;
 
        /* File caps or setid cancels ambient. */
-       if (has_cap || is_setid)
+       if (has_fcap || is_setid)
                cap_clear(new->cap_ambient);
 
        /*
@@ -800,26 +881,10 @@ skip:
        if (WARN_ON(!cap_ambient_invariant_ok(new)))
                return -EPERM;
 
-       /*
-        * Audit candidate if current->cap_effective is set
-        *
-        * We do not bother to audit if 3 things are true:
-        *   1) cap_effective has all caps
-        *   2) we are root
-        *   3) root is supposed to have all caps (SECURE_NOROOT)
-        * Since this is just a normal root execing a process.
-        *
-        * Number 1 above might fail if you don't have a full bset, but I think
-        * that is interesting information to audit.
-        */
-       if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
-               if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
-                   !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
-                   issecure(SECURE_NOROOT)) {
-                       ret = audit_log_bprm_fcaps(bprm, new, old);
-                       if (ret < 0)
-                               return ret;
-               }
+       if (nonroot_raised_pE(new, old, root_uid, has_fcap)) {
+               ret = audit_log_bprm_fcaps(bprm, new, old);
+               if (ret < 0)
+                       return ret;
        }
 
        new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
@@ -829,13 +894,11 @@ skip:
 
        /* Check for privilege-elevated exec. */
        bprm->cap_elevated = 0;
-       if (is_setid) {
+       if (is_setid ||
+           (!__is_real(root_uid, new) &&
+            (effective ||
+             __cap_grew(permitted, ambient, new))))
                bprm->cap_elevated = 1;
-       } else if (!uid_eq(new->uid, root_uid)) {
-               if (effective ||
-                   !cap_issubset(new->cap_permitted, new->cap_ambient))
-                       bprm->cap_elevated = 1;
-       }
 
        return 0;
 }
index 286171a16ed255e20c396fca595600488c059c2d..14cc7940b36d2d0a960a3fff9a87a649a50dbc64 100644 (file)
@@ -4600,6 +4600,82 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
        return 0;
 }
 
+static int smack_inode_copy_up(struct dentry *dentry, struct cred **new)
+{
+
+       struct task_smack *tsp;
+       struct smack_known *skp;
+       struct inode_smack *isp;
+       struct cred *new_creds = *new;
+
+       if (new_creds == NULL) {
+               new_creds = prepare_creds();
+               if (new_creds == NULL)
+                       return -ENOMEM;
+       }
+
+       tsp = new_creds->security;
+
+       /*
+        * Get label from overlay inode and set it in create_sid
+        */
+       isp = d_inode(dentry->d_parent)->i_security;
+       skp = isp->smk_inode;
+       tsp->smk_task = skp;
+       *new = new_creds;
+       return 0;
+}
+
+static int smack_inode_copy_up_xattr(const char *name)
+{
+       /*
+        * Return 1 if this is the smack access Smack attribute.
+        */
+       if (strcmp(name, XATTR_NAME_SMACK) == 0)
+               return 1;
+
+       return -EOPNOTSUPP;
+}
+
+static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
+                                       struct qstr *name,
+                                       const struct cred *old,
+                                       struct cred *new)
+{
+       struct task_smack *otsp = old->security;
+       struct task_smack *ntsp = new->security;
+       struct inode_smack *isp;
+       int may;
+
+       /*
+        * Use the process credential unless all of
+        * the transmuting criteria are met
+        */
+       ntsp->smk_task = otsp->smk_task;
+
+       /*
+        * the attribute of the containing directory
+        */
+       isp = d_inode(dentry->d_parent)->i_security;
+
+       if (isp->smk_flags & SMK_INODE_TRANSMUTE) {
+               rcu_read_lock();
+               may = smk_access_entry(otsp->smk_task->smk_known,
+                                      isp->smk_inode->smk_known,
+                                      &otsp->smk_task->smk_rules);
+               rcu_read_unlock();
+
+               /*
+                * If the directory is transmuting and the rule
+                * providing access is transmuting use the containing
+                * directory label instead of the process label.
+                */
+               if (may > 0 && (may & MAY_TRANSMUTE))
+                       ntsp->smk_task = isp->smk_inode;
+       }
+       return 0;
+}
+
 static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
@@ -4735,6 +4811,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
        LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
        LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),
+       LSM_HOOK_INIT(inode_copy_up, smack_inode_copy_up),
+       LSM_HOOK_INIT(inode_copy_up_xattr, smack_inode_copy_up_xattr),
+       LSM_HOOK_INIT(dentry_create_files_as, smack_dentry_create_files_as),
 };
 
 
index d330b060dcff2e7a02c56ca32a0d2973d68ea6e7..0f73fe30e37a571f9924ae484e2c27c495d3f614 100644 (file)
@@ -157,7 +157,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
        if (!buffer)
                return NULL;
 
-       tomoyo_convert_time(get_seconds(), &stamp);
+       tomoyo_convert_time(ktime_get_real_seconds(), &stamp);
 
        pos = snprintf(buffer, tomoyo_buffer_len - 1,
                       "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
index 21691b99e61f49f1495f0fb49ce15e7c368eeec4..25eed4b0b0e841040907ef9f0035fc99a128857a 100644 (file)
@@ -2257,7 +2257,7 @@ static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = {
 /* Timestamp counter for last updated. */
 static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT];
 /* Counter for number of updates. */
-static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
+static time64_t tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
 
 /**
  * tomoyo_update_stat - Update statistic counters.
@@ -2272,7 +2272,7 @@ void tomoyo_update_stat(const u8 index)
         * I don't use atomic operations because race condition is not fatal.
         */
        tomoyo_stat_updated[index]++;
-       tomoyo_stat_modified[index] = get_seconds();
+       tomoyo_stat_modified[index] = ktime_get_real_seconds();
 }
 
 /**
index e4097d7994b169746a934243f2db4a51c3ea4a98..7adccdd8e36d9b9117c9a8643495dcb2d880cc9a 100644 (file)
@@ -1037,7 +1037,7 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
                      bool (*check_entry) (struct tomoyo_request_info *,
                                           const struct tomoyo_acl_info *));
 void tomoyo_check_profile(void);
-void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp);
+void tomoyo_convert_time(time64_t time, struct tomoyo_time *stamp);
 void tomoyo_del_condition(struct list_head *element);
 void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
 void tomoyo_get_attributes(struct tomoyo_obj_info *obj);
index 580b318910f1484f6e3f7e7fdeefc5a5924d36ef..d3d9d9f1edb04a49abd4febc908d1fc294267d4f 100644 (file)
@@ -87,38 +87,17 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
  * @stamp: Pointer to "struct tomoyo_time".
  *
  * Returns nothing.
- *
- * This function does not handle Y2038 problem.
  */
-void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp)
+void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp)
 {
-       static const u16 tomoyo_eom[2][12] = {
-               { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-               { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-       };
-       u16 y;
-       u8 m;
-       bool r;
-       stamp->sec = time % 60;
-       time /= 60;
-       stamp->min = time % 60;
-       time /= 60;
-       stamp->hour = time % 24;
-       time /= 24;
-       for (y = 1970; ; y++) {
-               const unsigned short days = (y & 3) ? 365 : 366;
-               if (time < days)
-                       break;
-               time -= days;
-       }
-       r = (y & 3) == 0;
-       for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++)
-               ;
-       if (m)
-               time -= tomoyo_eom[r][m - 1];
-       stamp->year = y;
-       stamp->month = ++m;
-       stamp->day = ++time;
+       struct tm tm;
+       time64_to_tm(time64, 0, &tm);
+       stamp->sec = tm.tm_sec;
+       stamp->min = tm.tm_min;
+       stamp->hour = tm.tm_hour;
+       stamp->day = tm.tm_mday;
+       stamp->month = tm.tm_mon + 1;
+       stamp->year = tm.tm_year + 1900;
 }
 
 /**