Commit 95b68865 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of...

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (54 commits)
  tpm_nsc: Fix bug when loading multiple TPM drivers
  tpm: Move tpm_tis_reenable_interrupts out of CONFIG_PNP block
  tpm: Fix compilation warning when CONFIG_PNP is not defined
  TOMOYO: Update kernel-doc.
  tpm: Fix a typo
  tpm_tis: Probing function for Intel iTPM bug
  tpm_tis: Fix the probing for interrupts
  tpm_tis: Delay ACPI S3 suspend while the TPM is busy
  tpm_tis: Re-enable interrupts upon (S3) resume
  tpm: Fix display of data in pubek sysfs entry
  tpm_tis: Add timeouts sysfs entry
  tpm: Adjust interface timeouts if they are too small
  tpm: Use interface timeouts returned from the TPM
  tpm_tis: Introduce durations sysfs entry
  tpm: Adjust the durations if they are too small
  tpm: Use durations returned from TPM
  TOMOYO: Enable conditional ACL.
  TOMOYO: Allow using argv[]/envp[] of execve() as conditions.
  TOMOYO: Allow using executable's realpath and symlink's target as conditions.
  TOMOYO: Allow using owner/group etc. of file objects as conditions.
  ...

Fix up trivial conflict in security/tomoyo/realpath.c
parents 22712200 29412f0f
Encrypted keys for the eCryptfs filesystem
ECryptfs is a stacked filesystem which transparently encrypts and decrypts each
file using a randomly generated File Encryption Key (FEK).
Each FEK is in turn encrypted with a File Encryption Key Encryption Key (FEFEK)
either in kernel space or in user space with a daemon called 'ecryptfsd'. In
the former case the operation is performed directly by the kernel CryptoAPI
using a key, the FEFEK, derived from a user prompted passphrase; in the latter
the FEK is encrypted by 'ecryptfsd' with the help of external libraries in order
to support other mechanisms like public key cryptography, PKCS#11 and TPM based
operations.
The data structure defined by eCryptfs to contain information required for the
FEK decryption is called authentication token and, currently, can be stored in a
kernel key of the 'user' type, inserted in the user's session specific keyring
by the userspace utility 'mount.ecryptfs' shipped with the package
'ecryptfs-utils'.
The 'encrypted' key type has been extended with the introduction of the new
format 'ecryptfs' in order to be used in conjunction with the eCryptfs
filesystem. Encrypted keys of the newly introduced format store an
authentication token in its payload with a FEFEK randomly generated by the
kernel and protected by the parent master key.
In order to avoid known-plaintext attacks, the datablob obtained through
commands 'keyctl print' or 'keyctl pipe' does not contain the overall
authentication token, which content is well known, but only the FEFEK in
encrypted form.
The eCryptfs filesystem may really benefit from using encrypted keys in that the
required key can be securely generated by an Administrator and provided at boot
time after the unsealing of a 'trusted' key in order to perform the mount in a
controlled environment. Another advantage is that the key is not exposed to
threats of malicious software, because it is available in clear form only at
kernel level.
Usage:
keyctl add encrypted name "new ecryptfs key-type:master-key-name keylen" ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"
name:= '<16 hexadecimal characters>'
key-type:= 'trusted' | 'user'
keylen:= 64
Example of encrypted key usage with the eCryptfs filesystem:
Create an encrypted key "1000100010001000" of length 64 bytes with format
'ecryptfs' and save it using a previously loaded user key "test":
$ keyctl add encrypted 1000100010001000 "new ecryptfs user:test 64" @u
19184530
$ keyctl print 19184530
ecryptfs user:test 64 490045d4bfe48c99f0d465fbbbb79e7500da954178e2de0697
dd85091f5450a0511219e9f7cd70dcd498038181466f78ac8d4c19504fcc72402bfc41c2
f253a41b7507ccaa4b2b03fff19a69d1cc0b16e71746473f023a95488b6edfd86f7fdd40
9d292e4bacded1258880122dd553a661
$ keyctl pipe 19184530 > ecryptfs.blob
Mount an eCryptfs filesystem using the created encrypted key "1000100010001000"
into the '/secret' directory:
$ mount -i -t ecryptfs -oecryptfs_sig=1000100010001000,\
ecryptfs_cipher=aes,ecryptfs_key_bytes=32 /secret /secret
...@@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them. The master user key ...@@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them. The master user key
should therefore be loaded in as secure a way as possible, preferably early in should therefore be loaded in as secure a way as possible, preferably early in
boot. boot.
The decrypted portion of encrypted keys can contain either a simple symmetric
key or a more complex structure. The format of the more complex structure is
application specific, which is identified by 'format'.
Usage: Usage:
keyctl add encrypted name "new key-type:master-key-name keylen" ring keyctl add encrypted name "new [format] key-type:master-key-name keylen"
ring
keyctl add encrypted name "load hex_blob" ring keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name" keyctl update keyid "update key-type:master-key-name"
where 'key-type' is either 'trusted' or 'user'. format:= 'default | ecryptfs'
key-type:= 'trusted' | 'user'
Examples of trusted and encrypted key usage: Examples of trusted and encrypted key usage:
...@@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values: ...@@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values:
7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef 7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8 df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8
Create and save an encrypted key "evm" using the above trusted key "kmk": The initial consumer of trusted keys is EVM, which at boot time needs a high
quality symmetric key for HMAC protection of file metadata. The use of a
trusted key provides strong guarantees that the EVM key has not been
compromised by a user level problem, and when sealed to specific boot PCR
values, protects against boot and offline attacks. Create and save an
encrypted key "evm" using the above trusted key "kmk":
option 1: omitting 'format'
$ keyctl add encrypted evm "new trusted:kmk 32" @u $ keyctl add encrypted evm "new trusted:kmk 32" @u
159771175 159771175
option 2: explicitly defining 'format' as 'default'
$ keyctl add encrypted evm "new default trusted:kmk 32" @u
159771175
$ keyctl print 159771175 $ keyctl print 159771175
trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55 default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64 82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
5972dcb82ab2dde83376d82b2e3c09ffc 24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
$ keyctl pipe 159771175 > evm.blob $ keyctl pipe 159771175 > evm.blob
...@@ -132,14 +149,11 @@ Load an encrypted key "evm" from saved blob: ...@@ -132,14 +149,11 @@ Load an encrypted key "evm" from saved blob:
831684262 831684262
$ keyctl print 831684262 $ keyctl print 831684262
trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55 default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64 82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
5972dcb82ab2dde83376d82b2e3c09ffc 24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
Other uses for trusted and encrypted keys, such as for disk and file encryption
The initial consumer of trusted keys is EVM, which at boot time needs a high are anticipated. In particular the new format 'ecryptfs' has been defined in
quality symmetric key for HMAC protection of file metadata. The use of a in order to use encrypted keys to mount an eCryptfs filesystem. More details
trusted key provides strong guarantees that the EVM key has not been about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
compromised by a user level problem, and when sealed to specific boot PCR
values, protects against boot and offline attacks. Other uses for trusted and
encrypted keys, such as for disk and file encryption are anticipated.
...@@ -6408,7 +6408,7 @@ L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English) ...@@ -6408,7 +6408,7 @@ L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese) L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese) L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
W: http://tomoyo.sourceforge.jp/ W: http://tomoyo.sourceforge.jp/
T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.3.x/tomoyo-lsm/patches/ T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/
S: Maintained S: Maintained
F: security/tomoyo/ F: security/tomoyo/
......
...@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) ...@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
struct duration_t *duration_cap; struct duration_t *duration_cap;
ssize_t rc; ssize_t rc;
u32 timeout; u32 timeout;
unsigned int scale = 1;
tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.header.in = tpm_getcap_header;
tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
...@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip) ...@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (rc) if (rc)
goto duration; goto duration;
if (be32_to_cpu(tpm_cmd.header.out.length) if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
!= 4 * sizeof(u32)) be32_to_cpu(tpm_cmd.header.out.length)
goto duration; != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
return;
timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
/* Don't overwrite default if value is 0 */ /* Don't overwrite default if value is 0 */
timeout = be32_to_cpu(timeout_cap->a); timeout = be32_to_cpu(timeout_cap->a);
if (timeout && timeout < 1000) {
/* timeouts in msec rather usec */
scale = 1000;
chip->vendor.timeout_adjusted = true;
}
if (timeout) if (timeout)
chip->vendor.timeout_a = usecs_to_jiffies(timeout); chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->b); timeout = be32_to_cpu(timeout_cap->b);
if (timeout) if (timeout)
chip->vendor.timeout_b = usecs_to_jiffies(timeout); chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->c); timeout = be32_to_cpu(timeout_cap->c);
if (timeout) if (timeout)
chip->vendor.timeout_c = usecs_to_jiffies(timeout); chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->d); timeout = be32_to_cpu(timeout_cap->d);
if (timeout) if (timeout)
chip->vendor.timeout_d = usecs_to_jiffies(timeout); chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
duration: duration:
tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.header.in = tpm_getcap_header;
...@@ -575,23 +582,31 @@ void tpm_get_timeouts(struct tpm_chip *chip) ...@@ -575,23 +582,31 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (rc) if (rc)
return; return;
if (be32_to_cpu(tpm_cmd.header.out.return_code) if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
!= 3 * sizeof(u32)) be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
return; return;
duration_cap = &tpm_cmd.params.getcap_out.cap.duration; duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] = chip->vendor.duration[TPM_SHORT] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
chip->vendor.duration[TPM_MEDIUM] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
chip->vendor.duration[TPM_LONG] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
* value wrong and apparently reports msecs rather than usecs. So we * value wrong and apparently reports msecs rather than usecs. So we
* fix up the resulting too-small TPM_SHORT value to make things work. * fix up the resulting too-small TPM_SHORT value to make things work.
* We also scale the TPM_MEDIUM and -_LONG values by 1000.
*/ */
if (chip->vendor.duration[TPM_SHORT] < (HZ/100)) if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
chip->vendor.duration[TPM_SHORT] = HZ; chip->vendor.duration[TPM_SHORT] = HZ;
chip->vendor.duration[TPM_MEDIUM] *= 1000;
chip->vendor.duration[TPM_MEDIUM] = chip->vendor.duration[TPM_LONG] *= 1000;
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); chip->vendor.duration_adjusted = true;
chip->vendor.duration[TPM_LONG] = dev_info(chip->dev, "Adjusting TPM timeout parameters.");
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); }
} }
EXPORT_SYMBOL_GPL(tpm_get_timeouts); EXPORT_SYMBOL_GPL(tpm_get_timeouts);
...@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip) ...@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
u8 data[] = { u8 data[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 10, /* length */ 0, 0, 0, 10, /* length */
0, 0, 0, 83, /* TPM_ORD_GetCapability */ 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
}; };
tpm_transmit(chip, data, sizeof(data)); tpm_transmit(chip, data, sizeof(data));
...@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, ...@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
data = tpm_cmd.params.readpubek_out_buffer; data = tpm_cmd.params.readpubek_out_buffer;
str += str +=
sprintf(str, sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" "Algorithm: %02X %02X %02X %02X\n"
"Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X" "Encscheme: %02X %02X\n"
" %02X %02X %02X %02X %02X %02X %02X %02X\n" "Sigscheme: %02X %02X\n"
"Modulus length: %d\nModulus: \n", "Parameters: %02X %02X %02X %02X "
data[10], data[11], data[12], data[13], data[14], "%02X %02X %02X %02X "
data[15], data[16], data[17], data[22], data[23], "%02X %02X %02X %02X\n"
data[24], data[25], data[26], data[27], data[28], "Modulus length: %d\n"
data[29], data[30], data[31], data[32], data[33], "Modulus:\n",
be32_to_cpu(*((__be32 *) (data + 34)))); 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))));
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
str += sprintf(str, "%02X ", data[i + 38]); str += sprintf(str, "%02X ", data[i + 28]);
if ((i + 1) % 16 == 0) if ((i + 1) % 16 == 0)
str += sprintf(str, "\n"); str += sprintf(str, "\n");
} }
...@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev, ...@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
} }
EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
return sprintf(buf, "%d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
chip->vendor.duration_adjusted
? "adjusted" : "original");
}
EXPORT_SYMBOL_GPL(tpm_show_durations);
ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
return sprintf(buf, "%d %d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.timeout_a),
jiffies_to_usecs(chip->vendor.timeout_b),
jiffies_to_usecs(chip->vendor.timeout_c),
jiffies_to_usecs(chip->vendor.timeout_d),
chip->vendor.timeout_adjusted
? "adjusted" : "original");
}
EXPORT_SYMBOL_GPL(tpm_show_timeouts);
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
......
...@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, ...@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
char *); char *);
extern ssize_t tpm_show_temp_deactivated(struct device *, extern ssize_t tpm_show_temp_deactivated(struct device *,
struct device_attribute *attr, char *); struct device_attribute *attr, char *);
extern ssize_t tpm_show_durations(struct device *,
struct device_attribute *attr, char *);
extern ssize_t tpm_show_timeouts(struct device *,
struct device_attribute *attr, char *);
struct tpm_chip; struct tpm_chip;
...@@ -67,6 +71,7 @@ struct tpm_vendor_specific { ...@@ -67,6 +71,7 @@ struct tpm_vendor_specific {
unsigned long base; /* TPM base address */ unsigned long base; /* TPM base address */
int irq; int irq;
int probed_irq;
int region_size; int region_size;
int have_region; int have_region;
...@@ -81,7 +86,9 @@ struct tpm_vendor_specific { ...@@ -81,7 +86,9 @@ struct tpm_vendor_specific {
struct list_head list; struct list_head list;
int locality; int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */ unsigned long duration[3]; /* jiffies */
bool duration_adjusted;
wait_queue_head_t read_queue; wait_queue_head_t read_queue;
wait_queue_head_t int_queue; wait_queue_head_t int_queue;
......
...@@ -330,12 +330,12 @@ static int __init init_nsc(void) ...@@ -330,12 +330,12 @@ static int __init init_nsc(void)
pdev->dev.driver = &nsc_drv.driver; pdev->dev.driver = &nsc_drv.driver;
pdev->dev.release = tpm_nsc_remove; pdev->dev.release = tpm_nsc_remove;
if ((rc = platform_device_register(pdev)) < 0) if ((rc = platform_device_add(pdev)) < 0)
goto err_free_dev; goto err_put_dev;
if (request_region(base, 2, "tpm_nsc0") == NULL ) { if (request_region(base, 2, "tpm_nsc0") == NULL ) {
rc = -EBUSY; rc = -EBUSY;
goto err_unreg_dev; goto err_del_dev;
} }
if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
...@@ -382,10 +382,10 @@ static int __init init_nsc(void) ...@@ -382,10 +382,10 @@ static int __init init_nsc(void)
err_rel_reg: err_rel_reg:
release_region(base, 2); release_region(base, 2);
err_unreg_dev: err_del_dev:
platform_device_unregister(pdev); platform_device_del(pdev);
err_free_dev: err_put_dev:
kfree(pdev); platform_device_put(pdev);
err_unreg_drv: err_unreg_drv:
platform_driver_unregister(&nsc_drv); platform_driver_unregister(&nsc_drv);
return rc; return rc;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/freezer.h>
#include "tpm.h" #include "tpm.h"
#define TPM_HEADER_SIZE 10 #define TPM_HEADER_SIZE 10
...@@ -79,7 +80,7 @@ enum tis_defaults { ...@@ -79,7 +80,7 @@ enum tis_defaults {
static LIST_HEAD(tis_chips); static LIST_HEAD(tis_chips);
static DEFINE_SPINLOCK(tis_lock); static DEFINE_SPINLOCK(tis_lock);
#ifdef CONFIG_ACPI #ifdef CONFIG_PNP
static int is_itpm(struct pnp_dev *dev) static int is_itpm(struct pnp_dev *dev)
{ {
struct acpi_device *acpi = pnp_acpi_device(dev); struct acpi_device *acpi = pnp_acpi_device(dev);
...@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev) ...@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev)
return 0; return 0;
} }
#else
static int is_itpm(struct pnp_dev *dev)
{
return 0;
}
#endif #endif
static int check_locality(struct tpm_chip *chip, int l) static int check_locality(struct tpm_chip *chip, int l)
...@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force) ...@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)
static int request_locality(struct tpm_chip *chip, int l) static int request_locality(struct tpm_chip *chip, int l)
{ {
unsigned long stop; unsigned long stop, timeout;
long rc; long rc;
if (check_locality(chip, l) >= 0) if (check_locality(chip, l) >= 0)
...@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l) ...@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l)
iowrite8(TPM_ACCESS_REQUEST_USE, iowrite8(TPM_ACCESS_REQUEST_USE,
chip->vendor.iobase + TPM_ACCESS(l)); chip->vendor.iobase + TPM_ACCESS(l));
stop = jiffies + chip->vendor.timeout_a;
if (chip->vendor.irq) { if (chip->vendor.irq) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -1;
rc = wait_event_interruptible_timeout(chip->vendor.int_queue, rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
(check_locality (check_locality
(chip, l) >= 0), (chip, l) >= 0),
chip->vendor.timeout_a); timeout);
if (rc > 0) if (rc > 0)
return l; return l;
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else { } else {
/* wait for burstcount */ /* wait for burstcount */
stop = jiffies + chip->vendor.timeout_a;
do { do {
if (check_locality(chip, l) >= 0) if (check_locality(chip, l) >= 0)
return l; return l;
...@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ...@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
if ((status & mask) == mask) if ((status & mask) == mask)
return 0; return 0;
stop = jiffies + timeout;
if (chip->vendor.irq) { if (chip->vendor.irq) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -ETIME;
rc = wait_event_interruptible_timeout(*queue, rc = wait_event_interruptible_timeout(*queue,
((tpm_tis_status ((tpm_tis_status
(chip) & mask) == (chip) & mask) ==
mask), timeout); mask), timeout);
if (rc > 0) if (rc > 0)
return 0; return 0;
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else { } else {
stop = jiffies + timeout;
do { do {
msleep(TPM_TIMEOUT); msleep(TPM_TIMEOUT);
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
...@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); ...@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
* tpm.c can skip polling for the data to be available as the interrupt is * tpm.c can skip polling for the data to be available as the interrupt is
* waited for here * waited for here
*/ */
static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
int rc, status, burstcnt; int rc, status, burstcnt;
size_t count = 0; size_t count = 0;
u32 ordinal;
if (request_locality(chip, 0) < 0) if (request_locality(chip, 0) < 0)
return -EBUSY; return -EBUSY;
...@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
/* write last byte */ /* write last byte */
iowrite8(buf[count], iowrite8(buf[count],
chip->vendor.iobase + chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
TPM_DATA_FIFO(chip->vendor.locality));
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
&chip->vendor.int_queue); &chip->vendor.int_queue);
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
...@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
goto out_err; goto out_err;
} }
return 0;
out_err:
tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);
return rc;
}
/*
* If interrupts are used (signaled by an irq set in the vendor structure)
* tpm.c can skip polling for the data to be available as the interrupt is
* waited for here
*/
static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
int rc;
u32 ordinal;
rc = tpm_tis_send_data(chip, buf, len);
if (rc < 0)
return rc;
/* go and do it */ /* go and do it */
iowrite8(TPM_STS_GO, iowrite8(TPM_STS_GO,
chip->vendor.iobase + TPM_STS(chip->vendor.locality)); chip->vendor.iobase + TPM_STS(chip->vendor.locality));
...@@ -358,6 +391,47 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -358,6 +391,47 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
return rc; return rc;
} }
/*
* Early probing for iTPM with STS_DATA_EXPECT flaw.
* Try sending command without itpm flag set and if that
* fails, repeat with itpm flag set.
*/
static int probe_itpm(struct tpm_chip *chip)
{
int rc = 0;
u8 cmd_getticks[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0xf1
};
size_t len = sizeof(cmd_getticks);
int rem_itpm = itpm;
itpm = 0;
rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0)
goto out;
tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);
itpm = 1;
rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0) {
dev_info(chip->dev, "Detected an iTPM.\n");
rc = 1;
} else
rc = -EFAULT;
out:
itpm = rem_itpm;
tpm_tis_ready(chip);
release_locality(chip, chip->vendor.locality, 0);
return rc;
}
static const struct file_operations tis_ops = { static const struct file_operations tis_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
...@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, ...@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
NULL); NULL);
static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
static struct attribute *tis_attrs[] = { static struct attribute *tis_attrs[] = {
&dev_attr_pubek.attr, &dev_attr_pubek.attr,
...@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = { ...@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = {
&dev_attr_owned.attr, &dev_attr_owned.attr,
&dev_attr_temp_deactivated.attr, &dev_attr_temp_deactivated.attr,
&dev_attr_caps.attr, &dev_attr_caps.attr,
&dev_attr_cancel.attr, NULL, &dev_attr_cancel.attr,
&dev_attr_durations.attr,
&dev_attr_timeouts.attr, NULL,
}; };
static struct attribute_group tis_attr_grp = { static struct attribute_group tis_attr_grp = {
...@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id) ...@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
if (interrupt == 0) if (interrupt == 0)
return IRQ_NONE; return IRQ_NONE;
chip->vendor.irq = irq; chip->vendor.probed_irq = irq;
/* Clear interrupts handled with TPM_EOI */ /* Clear interrupts handled with TPM_EOI */
iowrite32(interrupt, iowrite32(interrupt,
...@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
resource_size_t len, unsigned int irq) resource_size_t len, unsigned int irq)
{ {
u32 vendor, intfcaps, intmask; u32 vendor, intfcaps, intmask;
int rc, i; int rc, i, irq_s, irq_e;
struct tpm_chip *chip; struct tpm_chip *chip;
if (!(chip = tpm_register_hardware(dev, &tpm_tis))) if (!(chip = tpm_register_hardware(dev, &tpm_tis)))
...@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
"1.2 TPM (device-id 0x%X, rev-id %d)\n", "1.2 TPM (device-id 0x%X, rev-id %d)\n",
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
if (!itpm) {
itpm = probe_itpm(chip);
if (itpm < 0) {
rc = -ENODEV;
goto out_err;
}
}
if (itpm) if (itpm)
dev_info(dev, "Intel iTPM workaround enabled\n"); dev_info(dev, "Intel iTPM workaround enabled\n");
...@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
if (intfcaps & TPM_INTF_DATA_AVAIL_INT) if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
dev_dbg(dev, "\tData Avail Int Support\n"); dev_dbg(dev, "\tData Avail Int Support\n");
/* get the timeouts before testing for irqs */
tpm_get_timeouts(chip);
/* INTERRUPT Setup */ /* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.read_queue);
init_waitqueue_head(&chip->vendor.int_queue); init_waitqueue_head(&chip->vendor.int_queue);
...@@ -540,11 +629,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -540,11 +629,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
if (interrupts) if (interrupts)
chip->vendor.irq = irq; chip->vendor.irq = irq;
if (interrupts && !chip->vendor.irq) { if (interrupts && !chip->vendor.irq) {
chip->vendor.irq = irq_s =
ioread8(chip->vendor.iobase + ioread8(chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality)); TPM_INT_VECTOR(chip->vendor.locality));
if (irq_s) {
irq_e = irq_s;
} else {
irq_s = 3;
irq_e = 15;
}
for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
iowrite8(i, chip->vendor.iobase + iowrite8(i, chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality)); TPM_INT_VECTOR(chip->vendor.locality));
if (request_irq if (request_irq
...@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
chip->vendor.iobase + chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality)); TPM_INT_ENABLE(chip->vendor.locality));
chip->vendor.probed_irq = 0;
/* Generate Interrupts */ /* Generate Interrupts */
tpm_gen_interrupt(chip); tpm_gen_interrupt(chip);
chip->vendor.irq = chip->vendor.probed_irq;
/* free_irq will call into tis_int_probe;
clear all irqs we haven't seen while doing
tpm_gen_interrupt */
iowrite32(ioread32
(chip->vendor.iobase +
TPM_INT_STATUS(chip->vendor.locality)),
chip->vendor.iobase +
TPM_INT_STATUS(chip->vendor.locality));
/* Turn off */ /* Turn off */
iowrite32(intmask, iowrite32(intmask,
chip->vendor.iobase + chip->vendor.iobase +
...@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
list_add(&chip->vendor.list, &tis_chips); list_add(&chip->vendor.list, &tis_chips);
spin_unlock(&tis_lock); spin_unlock(&tis_lock);
tpm_get_timeouts(chip);
tpm_continue_selftest(chip); tpm_continue_selftest(chip);
return 0; return 0;
...@@ -619,6 +726,29 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -619,6 +726,29 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
tpm_remove_hardware(chip->dev); tpm_remove_hardware(chip->dev);
return rc; return rc;
} }
static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
{
u32 intmask;
/* reenable interrupts that device may have lost or
BIOS/firmware may have disabled */
iowrite8(chip->vendor.irq, chip->vendor.iobase +
TPM_INT_VECTOR(chip->vendor.locality));
intmask =
ioread32(chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
intmask |= TPM_INTF_CMD_READY_INT
| TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
| TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
iowrite32(intmask,
chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
}
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
const struct pnp_device_id *pnp_id) const struct pnp_device_id *pnp_id)
...@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) ...@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
struct tpm_chip *chip = pnp_get_drvdata(dev); struct tpm_chip *chip = pnp_get_drvdata(dev);
int ret; int ret;
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
ret = tpm_pm_resume(&dev->dev); ret = tpm_pm_resume(&dev->dev);
if (!ret) if (!ret)
tpm_continue_selftest(chip); tpm_continue_selftest(chip);
...@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) ...@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
static int tpm_tis_resume(struct platform_device *dev) static int tpm_tis_resume(struct platform_device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
return tpm_pm_resume(&dev->dev); return tpm_pm_resume(&dev->dev);
} }
static struct platform_driver tis_drv = { static struct platform_driver tis_drv = {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define ECRYPTFS_KERNEL_H #define ECRYPTFS_KERNEL_H
#include <keys/user-type.h> #include <keys/user-type.h>
#include <keys/encrypted-type.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/fs_stack.h> #include <linux/fs_stack.h>
#include <linux/namei.h> #include <linux/namei.h>
...@@ -36,125 +37,18 @@ ...@@ -36,125 +37,18 @@
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/ecryptfs.h>
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
/* These flags indicate which features are supported by the kernel
* module; userspace tools such as the mount helper read
* ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
* how to behave. */
#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
#define ECRYPTFS_VERSIONING_XATTR 0x00000010
#define ECRYPTFS_VERSIONING_MULTKEY 0x00000020
#define ECRYPTFS_VERSIONING_DEVMISC 0x00000040
#define ECRYPTFS_VERSIONING_HMAC 0x00000080
#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION 0x00000100
#define ECRYPTFS_VERSIONING_GCM 0x00000200
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
| ECRYPTFS_VERSIONING_PUBKEY \
| ECRYPTFS_VERSIONING_XATTR \
| ECRYPTFS_VERSIONING_MULTKEY \
| ECRYPTFS_VERSIONING_DEVMISC \
| ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2)
/* The original signature size is only for what is stored on disk; all
* in-memory representations are expanded hex, so it better adapted to
* be passed around or referenced on the command line */
#define ECRYPTFS_SIG_SIZE 8
#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2)
#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX
#define ECRYPTFS_MAX_KEY_BYTES 64
#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
#define ECRYPTFS_DEFAULT_IV_BYTES 16 #define ECRYPTFS_DEFAULT_IV_BYTES 16
#define ECRYPTFS_FILE_VERSION 0x03
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192 #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32 #define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ #define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3) #define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
#define ECRYPTFS_DEFAULT_NUM_USERS 4 #define ECRYPTFS_DEFAULT_NUM_USERS 4
#define ECRYPTFS_MAX_NUM_USERS 32768 #define ECRYPTFS_MAX_NUM_USERS 32768
#define ECRYPTFS_XATTR_NAME "user.ecryptfs" #define ECRYPTFS_XATTR_NAME "user.ecryptfs"
#define RFC2440_CIPHER_DES3_EDE 0x02
#define RFC2440_CIPHER_CAST_5 0x03
#define RFC2440_CIPHER_BLOWFISH 0x04
#define RFC2440_CIPHER_AES_128 0x07
#define RFC2440_CIPHER_AES_192 0x08
#define RFC2440_CIPHER_AES_256 0x09
#define RFC2440_CIPHER_TWOFISH 0x0a
#define RFC2440_CIPHER_CAST_6 0x0b
#define RFC2440_CIPHER_RSA 0x01
/**
* For convenience, we may need to pass around the encrypted session
* key between kernel and userspace because the authentication token
* may not be extractable. For example, the TPM may not release the
* private key, instead requiring the encrypted data and returning the
* decrypted data.
*/
struct ecryptfs_session_key {
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002
#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004
#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008
u32 flags;
u32 encrypted_key_size;
u32 decrypted_key_size;
u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
};
struct ecryptfs_password {
u32 password_bytes;
s32 hash_algo;
u32 hash_iterations;
u32 session_key_encryption_key_bytes;
#define ECRYPTFS_PERSISTENT_PASSWORD 0x01
#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
u32 flags;
/* Iterated-hash concatenation of salt and passphrase */
u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
/* Always in expanded hex */
u8 salt[ECRYPTFS_SALT_SIZE];
};
enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
struct ecryptfs_private_key {
u32 key_size;
u32 data_len;
u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
u8 data[];
};
/* May be a password or a private key */
struct ecryptfs_auth_tok {
u16 version; /* 8-bit major and 8-bit minor */
u16 token_type;
#define ECRYPTFS_ENCRYPT_ONLY 0x00000001
u32 flags;
struct ecryptfs_session_key session_key;
u8 reserved[32];
union {
struct ecryptfs_password password;
struct ecryptfs_private_key private_key;
} token;
} __attribute__ ((packed));
void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok); void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok);
extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size); extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size);
extern void ecryptfs_from_hex(char *dst, char *src, int dst_size); extern void ecryptfs_from_hex(char *dst, char *src, int dst_size);
...@@ -185,11 +79,47 @@ struct ecryptfs_page_crypt_context { ...@@ -185,11 +79,47 @@ struct ecryptfs_page_crypt_context {
} param; } param;
}; };
#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
static inline struct ecryptfs_auth_tok *
ecryptfs_get_encrypted_key_payload_data(struct key *key)
{
if (key->type == &key_type_encrypted)
return (struct ecryptfs_auth_tok *)
(&((struct encrypted_key_payload *)key->payload.data)->payload_data);
else
return NULL;
}
static inline struct key *ecryptfs_get_encrypted_key(char *sig)
{
return request_key(&key_type_encrypted, sig, NULL);
}
#else
static inline struct ecryptfs_auth_tok *
ecryptfs_get_encrypted_key_payload_data(struct key *key)
{
return NULL;
}
static inline struct key *ecryptfs_get_encrypted_key(char *sig)
{
return ERR_PTR(-ENOKEY);
}
#endif /* CONFIG_ENCRYPTED_KEYS */
static inline struct ecryptfs_auth_tok * static inline struct ecryptfs_auth_tok *
ecryptfs_get_key_payload_data(struct key *key) ecryptfs_get_key_payload_data(struct key *key)
{ {
struct ecryptfs_auth_tok *auth_tok;
auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
if (!auth_tok)
return (struct ecryptfs_auth_tok *) return (struct ecryptfs_auth_tok *)
(((struct user_key_payload*)key->payload.data)->data); (((struct user_key_payload *)key->payload.data)->data);
else
return auth_tok;
} }
#define ECRYPTFS_MAX_KEYSET_SIZE 1024 #define ECRYPTFS_MAX_KEYSET_SIZE 1024
......
...@@ -1634,6 +1634,8 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, ...@@ -1634,6 +1634,8 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
int rc = 0; int rc = 0;
(*auth_tok_key) = request_key(&key_type_user, sig, NULL); (*auth_tok_key) = request_key(&key_type_user, sig, NULL);
if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
(*auth_tok_key) = ecryptfs_get_encrypted_key(sig);
if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) { if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
printk(KERN_ERR "Could not find key with description: [%s]\n", printk(KERN_ERR "Could not find key with description: [%s]\n",
sig); sig);
...@@ -1641,6 +1643,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, ...@@ -1641,6 +1643,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
(*auth_tok_key) = NULL; (*auth_tok_key) = NULL;
goto out; goto out;
} }
}
down_write(&(*auth_tok_key)->sem); down_write(&(*auth_tok_key)->sem);
rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok); rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
if (rc) { if (rc) {
......
/* /*
* Copyright (C) 2010 IBM Corporation * Copyright (C) 2010 IBM Corporation
* Author: Mimi Zohar <zohar@us.ibm.com> * Copyright (C) 2010 Politecnico di Torino, Italy
* TORSEC group -- http://security.polito.it
*
* Authors:
* Mimi Zohar <zohar@us.ibm.com>
* Roberto Sassu <roberto.sassu@polito.it>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -15,13 +20,17 @@ ...@@ -15,13 +20,17 @@
struct encrypted_key_payload { struct encrypted_key_payload {
struct rcu_head rcu; struct rcu_head rcu;
char *format; /* datablob: format */
char *master_desc; /* datablob: master key name */ char *master_desc; /* datablob: master key name */
char *datalen; /* datablob: decrypted key length */ char *datalen; /* datablob: decrypted key length */
u8 *iv; /* datablob: iv */ u8 *iv; /* datablob: iv */
u8 *encrypted_data; /* datablob: encrypted data */ u8 *encrypted_data; /* datablob: encrypted data */
unsigned short datablob_len; /* length of datablob */ unsigned short datablob_len; /* length of datablob */
unsigned short decrypted_datalen; /* decrypted data length */ unsigned short decrypted_datalen; /* decrypted data length */
u8 decrypted_data[0]; /* decrypted data + datablob + hmac */ unsigned short payload_datalen; /* payload data length */
unsigned short encrypted_key_format; /* encrypted key format */
u8 *decrypted_data; /* decrypted data */
u8 payload_data[0]; /* payload data + datablob + hmac */
}; };
extern struct key_type key_type_encrypted; extern struct key_type key_type_encrypted;
......
#ifndef _LINUX_ECRYPTFS_H
#define _LINUX_ECRYPTFS_H
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
/* These flags indicate which features are supported by the kernel
* module; userspace tools such as the mount helper read
* ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
* how to behave. */
#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
#define ECRYPTFS_VERSIONING_XATTR 0x00000010
#define ECRYPTFS_VERSIONING_MULTKEY 0x00000020
#define ECRYPTFS_VERSIONING_DEVMISC 0x00000040
#define ECRYPTFS_VERSIONING_HMAC 0x00000080
#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION 0x00000100
#define ECRYPTFS_VERSIONING_GCM 0x00000200
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
| ECRYPTFS_VERSIONING_PUBKEY \
| ECRYPTFS_VERSIONING_XATTR \
| ECRYPTFS_VERSIONING_MULTKEY \
| ECRYPTFS_VERSIONING_DEVMISC \
| ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2)
/* The original signature size is only for what is stored on disk; all
* in-memory representations are expanded hex, so it better adapted to
* be passed around or referenced on the command line */
#define ECRYPTFS_SIG_SIZE 8
#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2)
#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX
#define ECRYPTFS_MAX_KEY_BYTES 64
#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
#define ECRYPTFS_FILE_VERSION 0x03
#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
#define RFC2440_CIPHER_DES3_EDE 0x02
#define RFC2440_CIPHER_CAST_5 0x03
#define RFC2440_CIPHER_BLOWFISH 0x04
#define RFC2440_CIPHER_AES_128 0x07
#define RFC2440_CIPHER_AES_192 0x08
#define RFC2440_CIPHER_AES_256 0x09
#define RFC2440_CIPHER_TWOFISH 0x0a
#define RFC2440_CIPHER_CAST_6 0x0b
#define RFC2440_CIPHER_RSA 0x01
/**
* For convenience, we may need to pass around the encrypted session
* key between kernel and userspace because the authentication token
* may not be extractable. For example, the TPM may not release the
* private key, instead requiring the encrypted data and returning the
* decrypted data.
*/
struct ecryptfs_session_key {
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002
#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004
#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008
u32 flags;
u32 encrypted_key_size;
u32 decrypted_key_size;
u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
};
struct ecryptfs_password {
u32 password_bytes;
s32 hash_algo;
u32 hash_iterations;
u32 session_key_encryption_key_bytes;
#define ECRYPTFS_PERSISTENT_PASSWORD 0x01
#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
u32 flags;
/* Iterated-hash concatenation of salt and passphrase */
u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
/* Always in expanded hex */
u8 salt[ECRYPTFS_SALT_SIZE];
};
enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
struct ecryptfs_private_key {
u32 key_size;
u32 data_len;
u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
u8 data[];
};
/* May be a password or a private key */
struct ecryptfs_auth_tok {
u16 version; /* 8-bit major and 8-bit minor */
u16 token_type;
#define ECRYPTFS_ENCRYPT_ONLY 0x00000001
u32 flags;
struct ecryptfs_session_key session_key;
u8 reserved[32];
union {
struct ecryptfs_password password;
struct ecryptfs_private_key private_key;
} token;
} __attribute__ ((packed));
#endif /* _LINUX_ECRYPTFS_H */
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
*/ */
#include <linux/cgroup.h> #include <linux/cgroup.h>
#include <linux/cred.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init_task.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -1514,6 +1516,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1514,6 +1516,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
struct cgroup *root_cgrp = &root->top_cgroup; struct cgroup *root_cgrp = &root->top_cgroup;
struct inode *inode; struct inode *inode;
struct cgroupfs_root *existing_root; struct cgroupfs_root *existing_root;
const struct cred *cred;
int i; int i;
BUG_ON(sb->s_root != NULL); BUG_ON(sb->s_root != NULL);
...@@ -1593,7 +1596,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1593,7 +1596,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
BUG_ON(!list_empty(&root_cgrp->children)); BUG_ON(!list_empty(&root_cgrp->children));
BUG_ON(root->number_of_cgroups != 1); BUG_ON(root->number_of_cgroups != 1);
cred = override_creds(&init_cred);
cgroup_populate_dir(root_cgrp); cgroup_populate_dir(root_cgrp);
revert_creds(cred);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
} else { } else {
......
...@@ -73,7 +73,6 @@ static int may_change_ptraced_domain(struct task_struct *task, ...@@ -73,7 +73,6 @@ static int may_change_ptraced_domain(struct task_struct *task,
cred = get_task_cred(tracer); cred = get_task_cred(tracer);
tracerp = aa_cred_profile(cred); tracerp = aa_cred_profile(cred);
} }
rcu_read_unlock();
/* not ptraced */ /* not ptraced */
if (!tracer || unconfined(tracerp)) if (!tracer || unconfined(tracerp))
...@@ -82,6 +81,7 @@ static int may_change_ptraced_domain(struct task_struct *task, ...@@ -82,6 +81,7 @@ static int may_change_ptraced_domain(struct task_struct *task,
error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH); error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
out: out:
rcu_read_unlock();
if (cred) if (cred)
put_cred(cred); put_cred(cred);
......
...@@ -127,7 +127,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, ...@@ -127,7 +127,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
*inheritable = cred->cap_inheritable; *inheritable = cred->cap_inheritable;
*permitted = cred->cap_permitted; *permitted = cred->cap_permitted;
if (!unconfined(profile)) { if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
*effective = cap_intersect(*effective, profile->caps.allow); *effective = cap_intersect(*effective, profile->caps.allow);
*permitted = cap_intersect(*permitted, profile->caps.allow); *permitted = cap_intersect(*permitted, profile->caps.allow);
} }
......
...@@ -14,7 +14,7 @@ obj-y := \ ...@@ -14,7 +14,7 @@ obj-y := \
user_defined.o user_defined.o
obj-$(CONFIG_TRUSTED_KEYS) += trusted.o obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o
obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_KEYS_COMPAT) += compat.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_SYSCTL) += sysctl.o
/*
* ecryptfs_format.c: helper functions for the encrypted key type
*
* Copyright (C) 2006 International Business Machines Corp.
* Copyright (C) 2010 Politecnico di Torino, Italy
* TORSEC group -- http://security.polito.it
*
* Authors:
* Michael A. Halcrow <mahalcro@us.ibm.com>
* Tyler Hicks <tyhicks@ou.edu>
* Roberto Sassu <roberto.sassu@polito.it>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*/
#include <linux/module.h>
#include "ecryptfs_format.h"
u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok)
{
return auth_tok->token.password.session_key_encryption_key;
}
EXPORT_SYMBOL(ecryptfs_get_auth_tok_key);
/*
* ecryptfs_get_versions()
*
* Source code taken from the software 'ecryptfs-utils' version 83.
*
*/
void ecryptfs_get_versions(int *major, int *minor, int *file_version)
{
*major = ECRYPTFS_VERSION_MAJOR;
*minor = ECRYPTFS_VERSION_MINOR;
if (file_version)
*file_version = ECRYPTFS_SUPPORTED_FILE_VERSION;
}
EXPORT_SYMBOL(ecryptfs_get_versions);
/*
* ecryptfs_fill_auth_tok - fill the ecryptfs_auth_tok structure
*
* Fill the ecryptfs_auth_tok structure with required ecryptfs data.
* The source code is inspired to the original function generate_payload()
* shipped with the software 'ecryptfs-utils' version 83.
*
*/
int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok,
const char *key_desc)
{
int major, minor;
ecryptfs_get_versions(&major, &minor, NULL);
auth_tok->version = (((uint16_t)(major << 8) & 0xFF00)
| ((uint16_t)minor & 0x00FF));
auth_tok->token_type = ECRYPTFS_PASSWORD;
strncpy((char *)auth_tok->token.password.signature, key_desc,
ECRYPTFS_PASSWORD_SIG_SIZE);
auth_tok->token.password.session_key_encryption_key_bytes =
ECRYPTFS_MAX_KEY_BYTES;
/*
* Removed auth_tok->token.password.salt and
* auth_tok->token.password.session_key_encryption_key
* initialization from the original code
*/
/* TODO: Make the hash parameterizable via policy */
auth_tok->token.password.flags |=
ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET;
/* The kernel code will encrypt the session key. */
auth_tok->session_key.encrypted_key[0] = 0;
auth_tok->session_key.encrypted_key_size = 0;
/* Default; subject to change by kernel eCryptfs */
auth_tok->token.password.hash_algo = PGP_DIGEST_ALGO_SHA512;
auth_tok->token.password.flags &= ~(ECRYPTFS_PERSISTENT_PASSWORD);
return 0;
}
EXPORT_SYMBOL(ecryptfs_fill_auth_tok);
MODULE_LICENSE("GPL");
/*
* ecryptfs_format.h: helper functions for the encrypted key type
*
* Copyright (C) 2006 International Business Machines Corp.
* Copyright (C) 2010 Politecnico di Torino, Italy
* TORSEC group -- http://security.polito.it
*
* Authors:
* Michael A. Halcrow <mahalcro@us.ibm.com>
* Tyler Hicks <tyhicks@ou.edu>
* Roberto Sassu <roberto.sassu@polito.it>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*/
#ifndef __KEYS_ECRYPTFS_H
#define __KEYS_ECRYPTFS_H
#include <linux/ecryptfs.h>
#define PGP_DIGEST_ALGO_SHA512 10
u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok);
void ecryptfs_get_versions(int *major, int *minor, int *file_version);
int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok,
const char *key_desc);
#endif /* __KEYS_ECRYPTFS_H */
This diff is collapsed.
...@@ -251,6 +251,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) ...@@ -251,6 +251,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
if (IS_ERR(authkey_ref)) { if (IS_ERR(authkey_ref)) {
authkey = ERR_CAST(authkey_ref); authkey = ERR_CAST(authkey_ref);
if (authkey == ERR_PTR(-EAGAIN))
authkey = ERR_PTR(-ENOKEY);
goto error; goto error;
} }
......
...@@ -9,3 +9,64 @@ config SECURITY_TOMOYO ...@@ -9,3 +9,64 @@ config SECURITY_TOMOYO
Required userspace tools and further information may be Required userspace tools and further information may be
found at <http://tomoyo.sourceforge.jp/>. found at <http://tomoyo.sourceforge.jp/>.
If you are unsure how to answer this question, answer N. If you are unsure how to answer this question, answer N.
config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
int "Default maximal count for learning mode"
default 2048
range 0 2147483647
depends on SECURITY_TOMOYO
help
This is the default value for maximal ACL entries
that are automatically appended into policy at "learning mode".
Some programs access thousands of objects, so running
such programs in "learning mode" dulls the system response
and consumes much memory.
This is the safeguard for such programs.
config SECURITY_TOMOYO_MAX_AUDIT_LOG
int "Default maximal count for audit log"
default 1024
range 0 2147483647
depends on SECURITY_TOMOYO
help
This is the default value for maximal entries for
audit logs that the kernel can hold on memory.
You can read the log via /sys/kernel/security/tomoyo/audit.
If you don't need audit logs, you may set this value to 0.
config SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
bool "Activate without calling userspace policy loader."
default n
depends on SECURITY_TOMOYO
---help---
Say Y here if you want to activate access control as soon as built-in
policy was loaded. This option will be useful for systems where
operations which can lead to the hijacking of the boot sequence are
needed before loading the policy. For example, you can activate
immediately after loading the fixed part of policy which will allow
only operations needed for mounting a partition which contains the
variant part of policy and verifying (e.g. running GPG check) and
loading the variant part of policy. Since you can start using
enforcing mode from the beginning, you can reduce the possibility of
hijacking the boot sequence.
config SECURITY_TOMOYO_POLICY_LOADER
string "Location of userspace policy loader"
default "/sbin/tomoyo-init"
depends on SECURITY_TOMOYO
depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
---help---
This is the default pathname of policy loader which is called before
activation. You can override this setting via TOMOYO_loader= kernel
command line option.
config SECURITY_TOMOYO_ACTIVATION_TRIGGER
string "Trigger for calling userspace policy loader"
default "/sbin/init"
depends on SECURITY_TOMOYO
depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
---help---
This is the default pathname of activation trigger.
You can override this setting via TOMOYO_trigger= kernel command line
option. For example, if you pass init=/bin/systemd option, you may
want to also pass TOMOYO_trigger=/bin/systemd option.
obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
$(obj)/policy/profile.conf:
@mkdir -p $(obj)/policy/
@echo Creating an empty policy/profile.conf
@touch $@
$(obj)/policy/exception_policy.conf:
@mkdir -p $(obj)/policy/
@echo Creating a default policy/exception_policy.conf
@echo initialize_domain /sbin/modprobe from any >> $@
@echo initialize_domain /sbin/hotplug from any >> $@
$(obj)/policy/domain_policy.conf:
@mkdir -p $(obj)/policy/
@echo Creating an empty policy/domain_policy.conf
@touch $@
$(obj)/policy/manager.conf:
@mkdir -p $(obj)/policy/
@echo Creating an empty policy/manager.conf
@touch $@
$(obj)/policy/stat.conf:
@mkdir -p $(obj)/policy/
@echo Creating an empty policy/stat.conf
@touch $@
$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
@echo Generating built-in policy for TOMOYO 2.4.x.
@echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
@echo "\"\";" >> $@.tmp
@echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
@echo "\"\";" >> $@.tmp
@echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
@echo "\"\";" >> $@.tmp
@echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
@echo "\"\";" >> $@.tmp
@echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
@echo "\"\";" >> $@.tmp
@mv $@.tmp $@
$(obj)/common.o: $(obj)/builtin-policy.h
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /*
* security/tomoyo/common.c * security/tomoyo/securityfs_if.c
* *
* Securityfs interface for TOMOYO. * Copyright (C) 2005-2011 NTT DATA CORPORATION
*
* Copyright (C) 2005-2010 NTT DATA CORPORATION
*/ */
#include <linux/security.h> #include <linux/security.h>
...@@ -34,11 +32,11 @@ static int tomoyo_open(struct inode *inode, struct file *file) ...@@ -34,11 +32,11 @@ static int tomoyo_open(struct inode *inode, struct file *file)
*/ */
static int tomoyo_release(struct inode *inode, struct file *file) static int tomoyo_release(struct inode *inode, struct file *file)
{ {
return tomoyo_close_control(file); return tomoyo_close_control(file->private_data);
} }
/** /**
* tomoyo_poll - poll() for /proc/ccs/ interface. * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface.
* *
* @file: Pointer to "struct file". * @file: Pointer to "struct file".
* @wait: Pointer to "poll_table". * @wait: Pointer to "poll_table".
...@@ -63,7 +61,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait) ...@@ -63,7 +61,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos) loff_t *ppos)
{ {
return tomoyo_read_control(file, buf, count); return tomoyo_read_control(file->private_data, buf, count);
} }
/** /**
...@@ -79,7 +77,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, ...@@ -79,7 +77,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
static ssize_t tomoyo_write(struct file *file, const char __user *buf, static ssize_t tomoyo_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
return tomoyo_write_control(file, buf, count); return tomoyo_write_control(file->private_data, buf, count);
} }
/* /*
...@@ -135,14 +133,14 @@ static int __init tomoyo_initerface_init(void) ...@@ -135,14 +133,14 @@ static int __init tomoyo_initerface_init(void)
TOMOYO_DOMAINPOLICY); TOMOYO_DOMAINPOLICY);
tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
TOMOYO_EXCEPTIONPOLICY); TOMOYO_EXCEPTIONPOLICY);
tomoyo_create_entry("audit", 0400, tomoyo_dir,
TOMOYO_AUDIT);
tomoyo_create_entry("self_domain", 0400, tomoyo_dir, tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
TOMOYO_SELFDOMAIN); TOMOYO_SELFDOMAIN);
tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
TOMOYO_DOMAIN_STATUS);
tomoyo_create_entry(".process_status", 0600, tomoyo_dir, tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
TOMOYO_PROCESS_STATUS); TOMOYO_PROCESS_STATUS);
tomoyo_create_entry("meminfo", 0600, tomoyo_dir, tomoyo_create_entry("stat", 0644, tomoyo_dir,
TOMOYO_MEMINFO); TOMOYO_STAT);
tomoyo_create_entry("profile", 0600, tomoyo_dir, tomoyo_create_entry("profile", 0600, tomoyo_dir,
TOMOYO_PROFILE); TOMOYO_PROFILE);
tomoyo_create_entry("manager", 0600, tomoyo_dir, tomoyo_create_entry("manager", 0600, tomoyo_dir,
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment